Syncing big data

Using fragmented channels to synchronize data that wouldn't usually fit in a packet.

Synchronizing entities with byte[] or string bindings, or sending commands with byte[] or string arguments allows you to sync large amounts of custom data. However, if an entity update, or a single command, is too large to fit inside a single packet (where default MTU is 1280 bytes), then the entity update or the command will never be synchronized. To solve this problem, and be able to sync data of practically any size, you can use fragmented channels for synchronization of entities or commands.

Data synchronized over the fragmented channels shares the bandwidth with other data synchronized over other channels, but data sent over the non-fragmented channels has priority over fragmented data. Because the bandwidth is shared (not multiplied), very large data sent over a fragmented channel might be more delayed if you're already syncing a lot of data over other channels.

Watch out for the amount of data you're sending over the fragmented channel, since the default bandwidth is not very high. For example, at the default MTU of 1280 bytes and default send rate of 20Hz, the maximum data bandwidth is around 24KB/s (this is after taking part of the bandwidth for coherence headers). If no other data is sent over other channels, 100KB of data sent over a fragmented channel would take over 4 seconds to transfer to the Replication Server, and 4 more seconds to transfer to other Clients, which brings the total latency to over 8 seconds for 100KB of data. But 5KB of data would be synced to other clients in under 500ms.

Note that there is currently no reporting of transfer progress in the SDK. Because of that, when sending considerable amounts of data, the synchronization might feel stuck, but it's probably just taking time to transfer the data to the replication server and then to other clients.

In case you want to synchronize a considerable amount of data, which would be too slow using the default bandwidth, we recommend exploring other options such as Cloud Storage, rather than increasing the MTU or send rate.

Syncing big data over entity bindings

In the Advanced Settings of the CoherenceSync, you can change the Synchronization Channel of an entity. Choosing the Fragmented channel will synchronize creation, deletion, and all binding updates of the entity over the Fragmented channel, allowing you to sync data of any size.

Note that the commands targeting that entity will still be sent over any channel. See the commands section for more details.

Since you don't want to send most bindings over the fragmented channel, the recommended way is to move bindings that contain big data to a separate CoherenceSync, and set only the new CoherenceSync's Synchronization Channel to Fragmented. One way of grouping those two entities together is by making the big data Prefab a child of the original Prefab using the PrefabSyncGroup.

Note that the big data child object might not be replicated to the remote Clients at the same time as the parent object, so you need to be sure your game logic can handle a scenario where the big data child object is delayed.

Syncing big data over commands

You can send commands over the fragmented channel to any entity, no matter if the entity is synchronized over the Fragmented or Default channel. To send a command over the fragmented channel, use the SendCommandOverChannel(...) and SendCommandToChildrenOverChannel(...) overloads, passing either Fragmented or FragmentedOrdered channel (for ordered commands) as an argument.

var data = new byte[5 * 1024]; // 5KB of data
sync.SendCommandOverChannel<Player>(
    nameof(Player.SendData),
    MessageTarget.AuthorityOnly,
    Channel.Fragmented,
    data);

Last updated

Was this helpful?