In a nutshell, the Cloud Variables allow the worlds to save persistence data about the players. This can be accomplished by creating a cloud storage. Cloud storages are created within a Massive Loop server, and then can be assigned to worlds of your in then server. Cloud Storages share variables between the worlds which they are linked to, therefore you can create continuous experiences between separate worlds. Here, we will dive in on how to create a Cloud Storage, how to link it to a World, and how to user SDK Editor and Lua API to access and user these variables.
A cloud variable is a container that hold's simple information. In Lua, cloud variables can be read, or assigned values to through a specific API. These variables can contain players' score, in world currency balance and many other useful data which enhances the player experience through persistence.
The variables are stored as a Key-Value dictionary in the storage.
The key must be a Unique String Identifier for the variable. However, the keys required to be unique only within the scope.
The value can be any value from the allowed types:
Any other type variables will be discarded.
The Variables Scope⚓︎
The cloud variables can be stored under three different scopes.
- User Level variables
These variables belongs to users. This means only a user (a Lua script running on the user's client) can set these variables. Each user can have up to 25 variables assigned to them for each storage. These variable are shared across all the world which the storage is linked.
- World Level variables
World level variable belongs to the world. World can have up to 25 variable in the linked storage. The world variables can only be written by the world creator, but everyone else can read them. You can use this variable to set world states, total number of currencies, etc.
- **Server Level variables **
These variables function similarly to world variables, but they are set in the server level. These variable can only be written by the server admin, but similar to world variables, can be read by anyone. Similarly, these variables can be use to set states in a server level.
Examples on variable scopes⚓︎
Let's say we have a server which we created and uploaded two worlds to it. We also created a storage for this server and linked it to our worlds.
User Level: We can implement a common currency to be used between these world. Let say the in the world A, the players can fight enemies and earn Golds. We can store the amount of golds each players' earned in the User Level Variables. Since these variables are shared between the worlds with that storage linked, we can access how much Gold each player have in their balance. Let say we implement a shop in world B and we sell weapons to player with their gold. We can then access their gold balance, reduce the balance and instead assign a variable specifying the ownership of specific weapon to that player.
World Level: High level variable can be used to store states relative to their scope. In our example, we can implement a system in out combat world which we can control the difficulty of our AI enemies by a world level cloud variable. The world creator can change this value externally using the SDK editor. Therefore we can make fine-tuning to the combat without needing to re-upload the world.
Server Level: Similarly, we can create special themes for our worlds which we can activate, or deactivate based on a Server level cloud variables. Let say we place decorative objects in our worlds for Halloween or other event, which the world only activates those objects when we set a server values.
The cloud variable stored in a Storage. Storage is a container that contains all of the Server, World, and User level cloud variables. Storages are created as part of Massive Loop server and linked to worlds. As a storage owner, you can set the creators who can link the storage to their worlds.
To create a cloud storage, head to https://massiveloop.com, login and switch to your server. Click on server dropdown menu and click on Configure This Server.
Scroll down to Cloud storage accounts and click on
Specify a storage name and click on
In the storage settings, assign developers, including yourself, to be a member of this storage. From the users dropdown, select the developer and then click on
Now you can link your world to this cloud storage!
Linking a world to a cloud storage⚓︎
Open your world's setting page. Scroll down to Cloud Storage Account. Select the storage from the drop down and click
Only one storage account can be linked to any world.
Modifying World and Server Level variables From SDK Editor⚓︎
You can externally Read, Create, Update, or Delete cloud variables from the SDK editor. Open the Unity Project for your world with SDK package already installed. Open Massive Loop control panel, and open the Worlds page (indicated by a planet icon). Select the Storage tab from the left panel.
You can create world and server variables buy clicking on button for each levels. Lets create a world level variable called ScaryMode. We intend this variable to be a Boolean type.
When you click on the Add New button, a new row will appears. Now we can set the key, type and value for this variable:
Click on button to add this variable to the list. When we add click on the variable, the row will be updated showing the newly added variable. You may notice the variable key is in green color and there is a (Unsaved) notice appears on top. This indicated that there are changes to the variables, these changes are staged locally, but they are not pushed to the server yet.
You can click on to push all the changes to the server.
The color of variable key indicates the current state of that variable.
- Natural Color: (black or white depending the Unity Theme) Shows the current variable state in cloud. No unsaved local changes
- Green Color: Shows a new variable added which is not in the cloud yet.
- Red Color: Shows a variable marked for deletion.
- Yellow Color: Shows a variable changed (type or it's value)
Lets create a variable for the Server level called SeasonColor. We intend this variable to be a Color Type.
You may notice that the value editor changes based one the type of the variable. Lets save the changes.
Modifying the variable value and Type⚓︎
You can modify the Type by changing the type from drop down. When a variable type is changed, the old value is discarded and a type specific editor is shown for the value column.
You can easily modify the value of a variable by interacting with the value column.
Lets change the SeasonColor value to dark blue color, specifying winter.
As you notice, the key color changes to yellow, specifying an unsaved change to variable.
Now, lets change the SeasonColor type to String and assign value of "Winter":
Let's try deleting the SeasonColor by clicking on
You can cancel a delete by clicking on
Don't forget to Save your changes!
Using the Lua API we can perform the CRUD (create, read, update, delete) operation on cloud variables. When using the Lua API, we are mainly targeting the User level variables. The Lua API still can read the World and Server level variables, however, we can write to them only if the user which is the Lua code is executing is a world owner or server admin.
Lets get familiar with LUA API for cloud variables. At the center, we have CloudVariables class. We can access the cloud variables from this class. The
CloudVariables class contains references to each of the cloud variable levels as a
CloudVariableBank class. A variable Bank is where all of the cloud variables accessed.
flowchart BT CloudVariables ulv[(UserVariables)] --> CloudVariables wlv[(WorldVariables)] --> CloudVariables slv[(ServerVariables)] --> CloudVariables
You can check if the current world have access to a cloud storage, by checking the
if CloudVariables.IsEnabled then -- we have access to cloud storage end
Scoreboards and Aggregates⚓︎
A cloud variable with a number (double) type can be used as scoreboard and queried. Let's say we create and set a cloud variable with key "Score" to every player after they finish a game. We can use LUA API to query, let say Top 5 player with highest score.
Note that only the variables with number type considered for the scoreboard.
We can use the
CloudVariable:GetScoreBoard method to collect scoreboards. This method returns a
Promise, which we can attach handlers for the success or failure states. The success state contains an array of
---@param result ScoreBoardEntry local function OnSuccess(result) -- Success for i,v in ipairs(result) do Debug:Log(string.format("Rank: %02d, Player: %s, Score: %.2f",i, v.UserDisplayName, v.Value)); end end local function OnRejected() -- Rejected Debug:log("Cloud not collect scoreboard"); end ---@param err string local function OnError(err) Debug:Log(string.format("Failed: %s", err)); end if CloudVariables.IsEnabled then CloudVariables:GetScoreBoard("score").Then(OnSuccess, OnRejected).Catch(OnError); end
You can specify the order, start and total number of scoreboard entries to be collected by specifying the descending, skip and limit parameters.
Although it is not possible to access other users' cloud variables value, we can still get aggregate data about a variable. Aggregates are collected for a specified subject. A subject in this context can mean a User, World or Server. An aggregate data contains following information about the variable:
- Count: Total number of users who have the variable with given key.
- Sum: The sum of the values for all subject members with variable, if the variable type is a number.
- Avg: The average of the values for all subject members with variable, if the variable type is a number.
- Min: The minimum of the values for all subject members with variable, if the variable type is a number.
- Max: The maximum of the values for all subject members with variable, if the variable type is a number.
- StringMin: The minimum of the string values for all subject members with variable, if the variable type is a string.
- StringMax: The maximum of the string values for all subject members with variable, if the variable type is a string.
This method returns a promise with payload of a
CloudVariableSummary type object.
---@param result CloudVariableSummary local function OnSuccess(result) -- Success Debug:Log(string.format("Max Score: %.2f", result.NumMax)); end local function OnRejected() -- Rejected Debug:log("Cloud not summary"); end ---@param err string local function OnError(err) Debug:Log(string.format("Failed: %s", err)); end if CloudVariables.IsEnabled then CloudVariables:GetUserVariableSummary("score", VariableSubject.User).Then(OnSuccess,OnRejected).Catch(OnError); end
Accessing cloud variables with Lua API⚓︎
CloudVariable have the following properties which allow to subject related variable bank:
The type of these objects is
You can check if the bank is readable by accessing its
ReadOnly property. To check if a variable is defined, we can call
To read the value of the variable, call
GetVariable("keyName"), and to create or update a variable, call
Here is an example code, working with a user level cloud variable, storing the local user's score.
do local script = LUA.script; local SCORE_KEY = "score"; local localPlayerScore = 0; function script.Start() if CloudVariables.IsEnabled then if CloudVariables.UserVariables.KeyExists(SCORE_KEY) then localPlayerScore = CloudVariables.UserVariables.GetVariable(SCORE_KEY); else CloudVariables.UserVariables.SetVariable(SCORE_KEY, localPlayerScore); end end end --- Adds to local players score cloud variable ---@param score number function script.AddToPlayerScore(score) localPlayerScore = localPlayerScore + score; if CloudVariables.IsEnabled and not CloudVariables.UserVariables.ReadOnly then CloudVariables.UserVariables.SetVariable(SCORE_KEY, localPlayerScore); end end end
You can set a variable to be deleted by calling
MarkKeyForDeletion("KeyName") method. Setting a
nil value to variable also deletes the variable.
Saving the Values to Cloud⚓︎
The changes to the variables automatically pushed to server once every 3 minute or when the player leaves the room. However, you can read or write to cloud variables as much as you like.
It is still possible for the variable value to be lost and not to be saved in the cloud. In some cases you may need the variables to be saved immediately, for example, to ensure everyone's score is saved at the end of a match, where it is likely for players to leave the game, or close the client which might increase the likely hood of lost changes.
You can call
CloudVariables:RequestToPublish() method to request an immediate flush of all variables. Note that you may call this function once on every 3 minutes. Calling it more that once will not have any effect.