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)+

Per-player state views in CloudBehaviours

Define a tailored, per-player subset of your CloudBehaviour's state, such as each player's own hand in a card game.
Read time 3 minutesLast updated 12 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 CloudBehaviour holds the full state of your game, such as every player's hand in a card game. You usually don't want to send all of the state to every player. A
[SyncView]
method defines the tailored view that each player receives. Cloud Code builds each player's view and keeps it up to date automatically.
Important
A
[SyncView]
method controls which data each player receives. It doesn't restrict who can call your endpoints or change state. For access control, refer to Multiplayer game security in CloudBehaviours.

Define a per-player view

Mark a method
[SyncView("name")]
. Cloud Code calls the method once per recipient, with that player's ID, and sends the return value as part of that player's state. The Unity Editor also generates a client property named
name
with the method's return type.
The following example defines a per-player view of a card hand:
[StateScope(Scope.MultiplayerSession)]public class CardGame : CloudBehaviour{ // Store every hand. This field persists and stays in the cloud. [CloudCodeSerializeProperty] private Dictionary<string, List<Card>> _hands = new(); [SyncView("Hand")] internal List<Card> ProjectHand(string playerId) => _hands.TryGetValue(playerId, out var hand) ? hand : new List<Card>();}
The client bindings expose
public List<Card> Hand { get; private set; }
, which holds only that player's cards. The unfiltered dictionary never leaves the cloud.

Requirements

A
[SyncView]
method has the following requirements:
  • The method takes a single
    string
    parameter, the viewer's player ID, and returns the value that player receives. The method can't return
    void
    . The return type becomes the type of the generated client property. For example,
    List<Card> ProjectHand(string playerId)
    generates
    List<Card> Hand
    on the client.
  • The method is synchronous and non-generic.
  • The method is
    public
    or
    internal
    . A private
    [SyncView]
    method fails the build with
    CCSG142
    . A
    [SyncView]
    method never becomes an RPC, even when it's public.
The build doesn't check the following, but follow them so the view behaves as players expect:
  • Name the view after what the method returns, not after the method. For example, use
    [SyncView("Hand")]
    , not
    [SyncView("ProjectHand")]
    . The view name becomes the name of the property in the client bindings.
  • Don't change state in the method. The method runs once per recipient on every synchronization, so any state change repeats for every player.

Hide values from other players

Represent a hidden value as empty or absent, not as a stand-in value such as
0
. Otherwise, a player can't tell a hidden value from a real one.
The following example shows a sealed-bid auction, where each player receives only their own bid. A bid of
0
is valid, so a
0
in place of another player's bid looks like a real bid. Leave the other players' bids out instead:
[StateScope(Scope.MultiplayerSession)]public class AuctionGame : CloudBehaviour{ // Store every sealed bid in the cloud only. [CloudCodeSerializeProperty] private Dictionary<string, int> _bids = new(); // Leave out other players' bids instead of setting them to 0. [SyncView("Bids")] internal Dictionary<string, int> ProjectBids(string playerId) => _bids.Where(bid => bid.Key == playerId) .ToDictionary(bid => bid.Key, bid => bid.Value);}

Send player-specific data to one player

A per-player view applies to synchronized state only. An event always pushes to everyone in the scope. To send player-specific data to one player, use
Push.SendPlayerMessageAsync
instead of an event. Refer to Push channels in CloudBehaviours.

Additional resources