Help me craft a bare-bones position/rotation RPC?

Hey fellas! Delving into networked multiplayer. I have an RPC set up to broadcast a player’s position, body Y rotation, and head Y rotation. Looks like this…

private var myPosition : Vector3;
private var myRotation : float;
private var myLookRotation : float;

...

networkView.RPC("UpdateMovement", RPCMode.Others, myPosition, myRotation, myLookRotation);

This is called every 100 ms at most (if a value has changed.) Now from my experience with the Lacewing engine from Multimedia Fusion, I would save bandwidth by sending the rotations as single bytes (giving me 256 directions of rotation, which is enough for aesthetics).

I’ve heard about disabling timestamp and making RPCs unreliable to save bandwidth, but not descriptions of how to actually do it. How can I strip this RPC down to the bare minimum amount of data (within reason)?

Thanks guys!

Unity in itself doesn’t give you an option to strip RPC headers or send them unreliable. uLink does, if that’s what you truly want.

But do you?

If you want to send position/rotation updates and mean to send them unreliable, why use RPCs? There’s something called State Synchronization in Unity (and about every sensible networking engine), which does exactly that. I suggest you read on it here

As for compressing data to the bare minimum needed, you can convert the floats to shorts, or if you really don’t need so much precision, to chars that you can then synchronize.

It’s worth mentioning that if you do want to use RPCs, you can also convert them directly to bytes and send them in an array (if you know the first byte is always the head rotation, the second is always the body etc. you can easily unpack the array at the receiving end). This feature is undocumented (unfortunately) but kind of a ‘known secret’.


Now, why don’t you want to use RPCs for that?

You mentioned that you intend to send an update every ~100ms, if it has changed. This means that you have roughly 10 RPCs broadcasting from each of your players every second. Depending on the amount of players you have this can accumulate to quite a lot of RPCs, ignoring other RPCs you surely want to send as well (such as player instantiation etc).

Unity’s RPCs are reliable and ordered. This means the networkng engine numberes and stamps every RPC, and if one happens to drop on the way (which can happen quite frequently depending on network conditions in your environment) it will ‘hold back’ the others until the correct one arrives.

For example, if RPCs number 1, 2, 3 and 4 were sent, but number 2 dropped, Unity will wait with the network and put execution of RPC 3 and 4 on hold until it has received RPC 2. This can cause noticeable lag in your game, which no one wants.

This is why you want to send things that change frequently as unreliable, meaning they just broadcast without care who got them or if they got them at all. Out of order, missing or duplicate packets are all fine, no one cares.

Now it’s true that under the hood Unity’s RPCs are also unreliable, but so is the IP protocol. Unity and TCP/IP are doing some magic to turn those into reliable and ordered packets.

In short,

Use unreliable state synchronization for anything that changes frequently, and save the RPCs for things that you’re sure absolutely need to happen, and in the specific order they were sent, such as Player Instantiation or Destruction.

In your case, if you don’t want a NetworkView to send data if it hasn’t changed, you can verify that at the beginning of the OnSerializeNetworkView and just return, and it won’t broadcast anything at that time.