Documentation

Cloud Code

Version: 3.0.0  
Unity 6.7 (6000.7)+
Open Unity Dashboard

Cloud Code

Version: 3.0.0  
Unity 6.7 (6000.7)+

Synchronized state in CloudBehaviours

Declare synchronized state, read it in your game, and control when Cloud Code pushes updates.
Read time 5 minutesLast updated 2 days ago

Important
This page describes an experimental feature that might change significantly before release. It's not recommended to use or rely on experimental features in production environments due to potential instability.
A public field or property on a CloudBehaviour is synchronized state. The member's value is stored in the cloud, and the client bindings keep an up-to-date copy. In a
MultiplayerSession
scope, every member of the session receives updates. Private members never reach a client, so secrets such as a card deck or a dice seed stay in the cloud. To notify players that something happened, rather than share a current value, use a push channel. For a comparison, refer to Choose between a push channel and synchronized state.

Declare synchronized state

A public, non-static field synchronizes, and so does a public, non-static property with a setter. The setter can be private. The following example shows members that synchronize and members that don't:
[StateScope(Scope.MultiplayerSession)]public class MatchState : CloudBehaviour{ // These members synchronize. public int Round; public List<int> Scores; public int TurnNumber { get; set; } public int Seed { get; private set; } // This field stays in the cloud. private List<string> _deck;}
A
readonly
field or a property without a setter, such as a computed property, doesn't synchronize. The build reports a warning for each one. Synchronization and persistence follow different rules. For more information about persistence, refer to Player and match persistence in CloudBehaviours.
Values serialize as JSON. For how the client bindings represent types that you define, refer to Model types crossing the client boundary.

Read synchronized state in your game

The generated client bindings expose each synchronized member as a property. Only the client bindings set these properties, when they apply state from the server. Don't assign them from your client bindings script. A value you assign doesn't change the server state, and the next update overwrites it.
Subscribe to the
Synchronized
event to react to updates:
protected virtual void OnEnable(){ EnableClient(); Synchronized.AddListener(() => turnLabel.text = $"Round {Round}");}
The client bindings raise
Synchronized
after each applied update. An update comes from an RPC return, an incoming push, or the hydration that runs when the client's scope resolves. Hydration runs automatically, so a client that connects and does nothing else still holds the current server state.

Control synchronization manually

By default,
AutoSynchronize
is
true
. After each RPC returns, Cloud Code pushes updated synchronized state to the other clients in the scope. To batch several changes into a single push, set
AutoSynchronize
to
false
and call
SynchronizeAsync()
when you're ready:
public async Task ResolveRound(){ AutoSynchronize = false; Round++; Scores[0] += 10; await SynchronizeAsync();}
Cloud Code saves
AutoSynchronize
with the rest of the CloudBehaviour's state. After you set
AutoSynchronize
to
false
, it stays
false
for every later call in that scope until you set it back to
true
.
The calling client always receives the current state in the RPC return, regardless of
AutoSynchronize
.
A
Player
-scoped CloudBehaviour has no other clients to push to. State reaches that one client through RPC returns and hydration. A timer is the exception. A timer-triggered invocation has no RPC return, so Cloud Code pushes the updated state to the player. Refer to What a timer callback pushes.

Model types crossing the client boundary

When a synchronized field, an RPC, or an event uses a class, struct, or enum that you define in your cloud assembly, the Unity Editor generates a type with the same name in the client bindings. Your game can then work with the same data. The generated type is a data-only copy that keeps only the public fields and properties.
For example, the following inventory CloudBehaviour stores a list of items:
public class Item{ public string Name; public int Quantity = 1; // This data stays on the server. private string _dropTable; // This logic stays on the server. public bool IsStackable() => Quantity > 1;}[StateScope(Scope.Player)]public class Inventory : CloudBehaviour{ public List<Item> Items = new(); public void Add(Item item) => Items.Add(item);}
In your game,
Items
on the client bindings is a list of the following generated
Item
type:
public class Item{ public string Name { get; set; } public int Quantity { get; set; }}
The generated
Item
type affects your game in the following ways:
  • Your game reads
    Name
    and
    Quantity
    directly, for example to display the inventory.
  • IsStackable()
    doesn't exist in your game. To use the same rule on both sides, put the rule in a shared rules library, or compute the result on the server and synchronize it.
  • _dropTable
    never reaches your game.
  • The generated type doesn't copy default values such as
    = 1
    . An
    Item
    that your game creates, for example to pass to
    Add
    , starts with
    Quantity
    at
    0
    unless you set it.
A public property that can be read but not publicly assigned causes a compile-time error. Examples include a computed property and a property with a private setter. A public
readonly
field also causes a compile-time error. To learn where to put game logic instead, refer to Game organization in CloudBehaviours.
Use
List<T>
, an array, or
Dictionary<TKey, TValue>
for a collection field. Don't use a custom collection type, because Cloud Code can't serialize a custom collection to JSON and deserialize it back. A custom collection type causes a compile-time error when you use it as an RPC parameter or return value, or when it derives from a .NET collection type.
To share a single value differently per player, refer to Per-player state views in CloudBehaviours.

Additional resources