# 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.

> **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 it to every player. A `[SyncView]` method defines the tailored view each player is allowed to see, and Cloud Code builds and keeps each player's view in sync automatically.

> **Important:**
>
> A `[SyncView]` 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](/cloud-code/cloudbehaviours/secure-multiplayer-game-logic.md).

## Define a per-player view

Mark a method `[SyncView("name")]`. 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 `name` with the method's return type:

```csharp title="A per-player view of a card hand"
[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 `public List<Card> Hand { get; private set; }`, holding 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 sees. It 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 must be synchronous and non-generic.
* The method must be `public` or `internal`. A private `[SyncView]` method fails the build with `CCSG142`. A `[SyncView]` method never becomes an RPC, even when it's public.
* Name the view after what it returns, such as `"Hand"`, not after the method, such as `"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 `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 sees only their own bid. A bid of `0` is valid, so replacing the other players' bids with `0` would make them look like real bids. Leave them out instead:

```csharp title="Hiding values by leaving them out"
[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 `Push.SendPlayerMessageAsync` instead of an event. Refer to [Push channels in CloudBehaviours](/cloud-code/cloudbehaviours/push-channels.md).

## Additional resources

* [Turn-based game workflow](/cloud-code/cloudbehaviours/turn-based-game-workflow.md)
* [Synchronized state in CloudBehaviours](/cloud-code/cloudbehaviours/synchronized-state.md)
* [Multiplayer game security in CloudBehaviours](/cloud-code/cloudbehaviours/secure-multiplayer-game-logic.md)
