Reference
Every member of the networking package, what it does, and the rule attached to it.
Synced<T>
A field or auto-property on a behaviour. Becomes one replicated variable named after what you declared.
Value |
Read it; writing replicates, and only the owner may write |
Subscribe(handler) |
Run a handler on every client when the value arrives |
Subscribe(handler) taking (T old, T current) |
The same, told what it changed from as well as to |
Unsubscribe(handler) |
Stop; removing one never added does nothing |
MarkChanged() |
Say an element of a synced array changed, which an assignment cannot show |
Handlers run once a whole update has landed, so one may read another synced value on the same behaviour and see the value that arrived with it.
Room
Static, so anything can send: a behaviour, a plain class, an abstract one.
Send(message) |
To everybody |
Send(message, target) |
All, Master, Others |
Send(message, player) |
To one player, by their own id |
Subscribe<T>(handler) |
Hear every message of that type this client should act on |
Unsubscribe<T>(handler) |
Stop |
IsMaster |
Whether this client is the one arbitrating |
IsInstanceOwner |
Whether this client opened the instance |
Master |
Whoever is arbitrating, or null before the instance settles |
Players, PlayerCount |
Everybody here; Players allocates, so do not call it per frame |
LocalPlayer |
This client's player |
Bus, BusOf(player) |
The object carrying room messages, for a world that wants to look |
A handler may take (T) or (VRCPlayerApi, T). Both may subscribe to the same type and both run.
A handler may be private.
IsMaster is authority. IsInstanceOwner is permission. The master arbitrates and migrates
when that client leaves; the instance owner opened the place and in a public instance is usually
nobody present. A world that gates authority on the instance owner works perfectly in the
creator's own test instance and has no authority anywhere else.
Behaviour extensions
This object's own channel, written on the behaviour that is the object. Not the room: Room.Send
reaches every client through the room bus, and these travel on this object, so nothing has to carry
an id saying which object was meant.
this.Send(message) |
Sends on this object's own channel, to everybody |
this.Send(message, target), this.Send(message, player) |
The addressed forms |
this.Subscribe<T>(handler), this.Unsubscribe<T>(handler) |
A handler taking the message |
this.Subscribe<T>(handler) taking (VRCPlayerApi, T) |
The same, told who sent it |
this.Pending() |
How many sent messages VRChat has not accepted yet |
Sending requires owning the object. Only the owner's write replicates, so a non-owner is told now rather than finding out its message never left. Claim it first if any client should be able to send.
Pending() is zero almost always. One that stays above zero means the batches are larger than one
manual sync will take, and the world should send less.
A client acts on nothing sent before it arrived. Each batch carries when it was made, and a client that joined later drops it rather than replaying somebody else's history.
NetworkEvent
The base class for a message. Override what it carries:
Serialize(ByteWriter) |
Write the fields |
Deserialize(ByteReader) |
Read them back, in the same order |
A subclass needs a parameterless constructor, because a receiver builds one before it has anything to fill it with. A signal with no fields overrides neither method. Which type a message is travels as one byte, numbered across the whole project while building, so two behaviours in one world cannot disagree about what a number means.
ByteWriter/ByteReader, what Serialize/Deserialize above take, live in Udonite
Serialization — a dependency of this package, not part of it. Full member
list in its reference.
NetworkBus
One object's own message channel. Put it on an object and reference it.
channel.Send(message), channel.Send(message, target) |
Typed send on that object |
channel.Subscribe<T>(handler), channel.Unsubscribe<T>(handler) |
Hear that type on that object |
Received, Sent, Pending |
How many messages arrived, left, and are waiting for the wire |
Sender |
Who owns this channel, and therefore who its messages come from |
An object channel has one owner. Two clients sending on the same one contend for it, which is the reason room messages ride one object per player instead.
Ownership
IsMine(gameObject) |
Whether this client may write that object's synced values |
IsOwner(player, gameObject) |
Whether that player owns it |
Of(gameObject) |
Who owns it |
Claim(gameObject) |
Take it, unless something refuses |
GiveTo(player, gameObject) |
Hand it over |
IsClogged |
Whether VRChat is behind on this client's sends |
MasterOwned
A base class whose OnOwnershipRequest allows only the arbitrating client, for state nobody else
may write. Derive from it instead of writing the override.
NetworkTransform
Position, rotation and scale, sent by the owner and interpolated by everybody else. See Moving objects for the settings and what to expect from playback.