Two clients in a world have to agree on something. VRChat gives you two ways to do that, and they
solve different problems badly if you pick the wrong one.

**A synced variable is a fact that everybody holds.** A score, a door's open or shut, whose turn it
is. It survives: somebody walking in ten minutes late gets the current value without anybody
resending it.

**A message is something that happened once.** A hit landed, a round started, a button was pressed.
Sending it as a variable goes wrong in ways that look like nothing at all: assigning the same value
twice is one change, so two identical hits become one; a late joiner receives the last hit of a
fight they missed as though it just happened; and only the owner may write, so two players hitting
the same target fight over the variable and one hit disappears with nothing said.

This package is both, with the parts that usually go wrong handled.

```csharp
public class Door : UdoniteBehaviour
{
    private Synced<bool> open = new Synced<bool>();

    public override void Start()
    {
        open.Subscribe(OnOpenChanged);
        Room.Subscribe<Knocked>(OnKnocked);
    }

    public override void Interact()
    {
        open.Value = !open.Value;      // replicated, and every client's handler runs
        Room.Send(new Knocked());      // heard once by everybody, sender included
    }

    private void OnOpenChanged(bool value) => panel.SetActive(value);

    private void OnKnocked(Knocked message) => sound.Play();
}
```

`Room.Send` goes to the whole room, and anybody may send. 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. [Messages](/docs/net/messages) has both.

`open.Value = ...` writes the variable and asks VRChat to replicate it; there is no
`RequestSerialization` to forget. `Subscribe` runs your handler on every client when the value
arrives, once the whole update has landed rather than while half of it is still the old value.

## Who needs to own what

Ownership is VRChat's, not this package's: only the owner's write to an object replicates. What
differs is what each thing does when you are not the owner.

| what you do | who has to own it | if you do not |
|---|---|---|
| Write a `Synced<T>` value | the object holding the field | the write stays on your client, and the next value to arrive overwrites it |
| `this.Send` on this object's channel | this object | nothing is staged and nothing is delivered, said once in the console |
| `channel.Send` on a `NetworkBus` | that bus's object | the same |
| `Room.Send` | nobody | every client writes to its own player object's bus, so there is nothing to contend for |
| Move a `NetworkTransform` | the object | the owner sends and everybody else interpolates towards it |

**A room message is the one that needs no owner**, which is the main reason to prefer it when any
client may act. An object's channel and a synced field both come down to one writer, so a world
where anybody may act on the object claims it first:

```csharp
if (!Ownership.IsMine(gameObject))
    Ownership.Claim(gameObject);
```

A pickup or an `Interact` usually already claims it. `MasterOwned` is the opposite case: derive from
it and only the arbitrating client can own the object, for state nobody else may write.

## What is here

| | |
|---|---|
| `Synced<T>` | A variable every client holds, that tells you when it changes |
| `Room` | Send and subscribe to typed messages; who is here, who is arbitrating |
| `NetworkEvent` | A message with fields, rather than a bag of bytes |
| `NetworkBus` | One object's own message channel, when a message is about that object |
| `NetworkTransform` | Position, rotation and scale, interpolated, with teleport detection |
| `Ownership` | Who owns an object, and taking or giving it |
| `MasterOwned` | A base class for an object only the arbitrating client may own |

## What you do not have to set up

Room messages need one object in the scene to carry them, because a message has to be written to
something a client owns and nothing can create that while a world runs. **The package adds it for
you** the first time a behaviour in your world sends or subscribes, and says so once in the
console. A world that never sends gets nothing added to it.

If you would rather place it yourself, put a `NetworkBus` on an object carrying `VRCPlayerObject`
and yours is used instead. It is found by its components, never by its name.

**Udonite → Open Window → Settings → Net** has a toggle for this: turn it off and the package
never touches the scene, whether or not your world sends anything — placing the bus is then
entirely yours to do. On is the default. This one setting lives in `ProjectSettings/`, committed
like the rest of what the project excludes, because it is a fact about who owns the scene rather
than one developer's own preference.
