## Installation

First, add the networking package to your Unity project via VCC (VRChat Creator Companion). Open your project's `vccproject.json` and add the package, or use the VCC interface to install it directly.

Once installed, the package is available in your project and you can start using the networking APIs below.

## Share a value

```csharp
public class Scoreboard : UdoniteBehaviour
{
    private Synced<int> score = new Synced<int>();

    public override void Interact()
    {
        score.Value = score.Value + 1;
    }
}
```

`Synced<T>` is a field on your behaviour. Writing `.Value` stores it and asks VRChat to replicate,
so there is no serialization call to remember and no attribute to pair with a sync mode.

**Only the owner of the object may write it.** A write on a client that does not own the object
stays on that client. Take ownership first if anyone should be able to change it:

```csharp
public override void Interact()
{
    Ownership.Claim(gameObject);
    score.Value = score.Value + 1;
}
```

## Hear when it changes

```csharp
public override void Start()
{
    score.Subscribe(OnScoreChanged);
}

private void OnScoreChanged(int value)
{
    label.text = value.ToString();
}
```

The handler runs on every client, including the one that wrote it, so the display is built once and
not twice. It runs **after the whole update has arrived**, which matters the moment you have two
synced values: a handler that reads a sibling gets the value that came in the same update rather
than whatever was there before.

The handler can be private. It is called from inside your own behaviour, so nothing outside needs
to be able to name it.

## Send a message

A message is a class with the fields you want to send:

```csharp
public class Scored : NetworkEvent
{
    public int playerId;
    public int points;

    public override void Serialize(ByteWriter writer)
    {
        writer.WriteInt32(playerId);
        writer.WriteInt32(points);
    }

    public override void Deserialize(ByteReader reader)
    {
        playerId = reader.ReadInt32();
        points = reader.ReadInt32();
    }
}
```

Send it, and hear it:

```csharp
public override void Start()
{
    Room.Subscribe<Scored>(OnScored);
}

public override void Interact()
{
    Room.Send(new Scored { playerId = 1, points = 10 });
}

private void OnScored(Scored message)
{
    Debug.Log(message.points + " to player " + message.playerId);
}
```

**`Room.Send` sends to the whole room**, and being static it works from a plain class as well as
from a behaviour. A message about one particular object travels on that object instead, written as
`this.Send` on the behaviour that is the object, and that one requires owning it. Both are in
[Messages](/docs/net/messages).

**Anybody can send.** Unlike a synced value there is no owner to be, which is why a message is the
right shape for "somebody did something" and a variable is the right shape for "this is how things
are".

Every client hears it once, in the order it was sent, including the client that sent it. A player
who joins afterwards hears nothing they missed, which is what you want from an event and the
opposite of what you want from a value.

## Who sent it

Take a second parameter when it matters:

```csharp
private void OnScored(VRCPlayerApi sender, Scored message)
{
    Debug.Log(sender.displayName + " scored");
}
```

Both shapes can subscribe to the same message type and both run. Most handlers do not care who
sent it, which is why the sender is not in every signature.

## Where to go next

`Synced<T>` in full, including arrays and the one case the compiler cannot see, is in
[Synced values](/docs/net/synced-values). Addressing, object channels and what the wire actually
costs are in [Messages](/docs/net/messages).
