Per-player state views in CloudBehaviours
Define a tailored, per-player slice of your CloudBehaviour's state, such as a private hand in a card game.
Read time 3 minutesLast updated 16 days ago
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 it to every player. A method defines the tailored view each player is allowed to see, and Cloud Code builds and keeps each player's view in sync automatically.
[SyncView]Define a per-player view
Mark a method . The method is the state on the wire: Cloud Code calls it once per recipient, with that player's ID, and generates a read-only property named with the method's return type:
[SyncView("name")]name[StateScope(Scope.MultiplayerSession)]public class CardGame : CloudBehaviour{ [CloudCodeSerializeProperty] private Dictionary<string, List<Card>> _hands = new(); // Every hand, persisted and cloud-only [SyncView("Hand")] internal List<Card> ProjectHand(string playerId) => _hands.TryGetValue(playerId, out var hand) ? hand : new List<Card>();}
The client sees , holding only that player's cards. The unfiltered dictionary never leaves the cloud.
public List<Card> Hand { get; private set; }Requirements
A method has the following requirements:
[SyncView]- The method takes a single parameter, the viewer's player ID, and returns the value that player sees. It can't return
string. The return type becomes the type of the generated client property. For example,voidgeneratesList<Card> ProjectHand(string playerId)on the client.List<Card> Hand - The method must be synchronous and non-generic.
- The method must be or
public. A privateinternalmethod fails the build with[SyncView]. ACCSG142method never becomes an RPC, even when it's public.[SyncView] - Name the view after what it returns, such as , not after the method, such as
"Hand"."ProjectHand" - Keep the method free of side effects. It runs once per recipient on every synchronization, so it must not alter state in any way.
- Hide a value as empty or absent, not as a stand-in such as . Otherwise a player can't tell a hidden value from a real one.
0
The following example shows a sealed-bid auction, where each player sees only their own bid. A bid of is valid, so replacing the other players' bids with would make them look like real bids. Leave them out instead:
00[StateScope(Scope.MultiplayerSession)]public class AuctionGame : CloudBehaviour{ [CloudCodeSerializeProperty] private Dictionary<string, int> _bids = new(); // Every sealed bid, cloud-only [SyncView("Bids")] internal Dictionary<string, int> ProjectBids(string playerId) => _bids.Where(bid => bid.Key == playerId) // Other players' bids are absent, not 0 .ToDictionary(bid => bid.Key, bid => bid.Value);}
Send to specific players
A per-player view applies to synchronized state only. An event always pushes to everyone in the scope. To send private data to one player, use instead of an event. Refer to Push channels in CloudBehaviours.
Push.SendPlayerMessageAsync