Bandwidth Overheads of UNET HLAPI headers / features (ClientRPC, Command, SyncVar)

Hey,

optimization of bandwidth consumption is an essential issue for multiplayer games.

Unfortunately, I have not found a documentation of the bandwidth consumptions / overheads of UNET HLAPI features such as ClientRPC, Command and SyncVar.

Especially in order to create a decent network architecture design, I would like to know how much bandwidth is basically consumed by these functions at bare bones (e.g. header data only, without the actual data). This information seems to be crucial in order to implement proper designs and bandwidth optimizations.

For example, if I send a ClientRPC with just a single byte, how much bandwidth does it actually consume in total?
Same question for SyncVar and Command.

Any help is much appreciated.

1 Like

Well I can not say it for sure how much is added but at least for ClientRPC and Command there is an additional NetworkHash128 (128 bits) for the name of the method in question.

Really? 16 bytes? That seems a little excessive. Couldn’t they generate hashtable or something with single byte keys?

If I remember correctly, the hash is used to identify the function and is unique across the entire build. If you used a single byte you would be limited to ~256 clientRPC/Commands across the build or would need to track hashes in a more possibly unreliable way. The hash is stored in a static dictionary on NetworkBehaviour or NetworkIdentity with the class type and function associated with it.

The packet payload for a RPC message is 2 bytes for size, 2 bytes for RPC message type, packed 1-5 bytes for hash, packed 1-5 bytes for netid plus any arguments passed to RPC function.

1 Like

Thanks for the input guys.

So, without any arguments, a ClientRPC would consume 6 bytes at min. and 14 bytes at max in the very worst case.

What about SyncVars and Commands?

@aabramychev, it would be nice if a UNITY staff member would jump in to make sure that such information are added to the docs.

Command message: 2 bytes size, 2 bytes Command type(5), packed 1-5 bytes hash, packed 1-5 bytes netid plus arguments.

SyncList message: 2 bytes size, 2 bytes SyncList type(9), packed 1-5 bytes netid, packed 1-5 bytes CmdHash?, 1 byte SyncList operation, packed 1-5 bytes itemIndex plus arguments.

SyncVar message: 2 bytes size, 2 bytes SyncVar type(8), packed 1-5 bytes netid, plus (either all syncvars or dirty syncvars + packed 1-5 bytes for dirty bits) for each dirty NetworkBehaviour. A SyncVar message is set for each dirty channel for each NetworkIdentity.

2 Likes

What about the bandwidth of a NetworkTransform? They are 9 floats, each 4 Bytes, right? So it should be 36 Bytes. But here are my doubts:

  1. Does it synchronize always all nine values or it only sends changed ones?
  2. Does it compress the data?
  3. How much is in size the header of the packet sent?
    So, how much data does it send a NetworkTransform?
    Thanks in advance!

It uses the SyncVar message, It seems to sync all values when dirty bit is set, rotation and spin axis will be compressed based on Compression Value. Rotation and Spin axis will only be sent if Axis Sync is set.
For SyncTransform arguments are: 12 bytes position, 0-3 rotation angles based on axis sync * (2 or 4 bytes based on compression)
For Sync2D arguments are: 8 bytes position, 8 bytes velocity, (2 or 4 bytes) if axis sync, (2 or 4 bytes) if sync spin
For Sync3D arguments are: 12 bytes position, 12 bytes velocity, 0-3 rotation angles based on axis sync * (2 or 4 bytes based on compression), 0-3 spin angles based on axis sync and sync spin * (2 or 4 bytes based on compression)
For SyncCharacterController arguments are: 12 bytes position, 0-3 rotation angles based on axis sync * (2 or 4 bytes based on compression)

Actually there are more reliable ways to compress hash values and recurring strings like Huffman coding but i’m not sure if it is worthwhile here or not.