The data transfer chain
DataTransferer, the type you actually use, is the last link in an eight-level
inheritance chain built on Process:
Process → PlayerTracker → ReadyCheckProcess → DataChunker → ChunkedTransferSession → DataSender → DataChunkReceiver → DataSenderReceiver → DataTransferer. Each layer adds one
concern on top of the one below it, so this section documents them bottom-up in that same
order. Reading DataTransferer's page without the ones before it skips the reasoning
behind most of what it does.
The problem being solved
VRChat caps the total parameter size of a single network event at 16 KB and Udon's overall outgoing bandwidth to about 11 KB/s, so sending an arbitrary string to a set of players means splitting it into chunks, sending them one at a time, and confirming each one actually arrived before sending the next, all while players can join, leave, get suspended, or have ownership of the sending object change mid-transfer. Each layer in the chain exists to handle one slice of that: chunking the data, sequencing the chunks through a ready check, broadcasting lifecycle events, validating and reassembling what arrives, and exposing a clean public API on top.
Reading order
Read these in order; each page assumes the ones before it:
- DataChunker: splits and validates the raw string, no networking or process state of its own.
- ChunkedTransferSession: sequences one chunk's ready check after another.
- DataSender: broadcasts the sequencing transitions as networked lifecycle events.
- DataChunkReceiver: validates, stores, and acknowledges each incoming chunk.
- DataSenderReceiver: wraps the receiver's raw
hooks into a clean
Last*/event API. - DataTransferer: the type you actually use, adding only transfer-focused event names on top.
What you actually use
Unless you're extending the chain itself, you only interact with DataTransferer: call
TransferData(data, playerIds), subscribe to its events, read LastData when a transfer
completes. Everything on the intermediate pages exists to explain why DataTransferer
behaves the way it does under failure conditions (a player leaving mid-transfer, an
ownership handover between chunks, a malicious direct call to one of the network-callable
methods), not to hand you a separate API surface at each layer.