Search Unity

Network Bandwidth: NetworkInstanceId vs. Integer vs. Short

Discussion in 'Multiplayer' started by moco2k, Aug 27, 2015.

  1. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Hey everyone,

    let's say I need unique identifiers to identify particular objects across the network, players for instance.
    For example, a player has performed a particular action (e.g. shoot). The action has been registered on the server (e.g. by a Command). Then the server informs all clients about the action (e.g. by ClientRPC). Now all clients need to know which action has been performed and which player did it. Thus, we could pass an int for the actionId and the NetworkInstanceId to identify the shooting player. However, we could also prepare some kind of PlayerTable which uses integers, so that we only need to pass an integer to identify the player.

    My actual question is: Does transmission of NetworkInstanceId over network use more bandwidth than transmission of simple integers? Because NetworkInstanceId seems to be some kind of struct so I don't know.. In case that it consumes more bandwidth, is the difference to integer relevant/significant or is it not even worth to spend time on optimizations here?

    A second question: What about using shorts instead of integers? Is it recommended, if small values are sufficient? Or does integer optimization prevent shorts from being more useful here so we should always go with int?

    Anyways, right now, my stomatch tells me that passing NetworkInstanceId across the network for unique identification is just fine, but I just want to be really sure on this.

    Thanks for help! :)
     
  2. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    the NetworkInstanceId is transferred using NetworkWriter.WritePackedUInt32() - as are all 32bit and 16bit integers. This is a variable length format specified here: http://sqlite.org/src4/doc/trunk/www/varint.wiki

    so no. using a short will not use less bandwidth.
     
    moco2k likes this.
  3. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Ah, thanks for the fast reply. That makes it clear.
     
  4. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Seanr, I have one more question on this: Is your statement only true for NetworkInstanceId, or for all integers being transferred?

    Let's say I want to transfer an int variable over the network and I know that the variable will never exceed a value of 100. Thus, I could convert it to byte before sending over network (or even use byte in the first place).

    Does this actually help to reduce bandwidth?
    Or is every integer being transferred in variable length format when I use HLAPI mechanics like SyncVar, Command or ClientRPC?
     
  5. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    moco2k likes this.
  6. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Thanks, this is good to know.

    I think it would be helpful to somewhere have some bundled information on bandwidth consumption stuff, optimization and best practices. Maybe either here in the forums as a sticky thread, or in the documentation. This seems to be especially significant considering that we need to optimize for the bandwidth limiter which the relay server uses.
     
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    It helps to be aware of the difference in signed vs unsigned integers here. I didn't do the math on the sqlite encoding but it looks to be based on MSB int encoding which is based on setting the most significant bit at the end of an integer, and it doesn't work for signed integers. They would gain some here by using something like zigzag encoding on signed integers but right now signed integers don't look to have any optimization. I could have missed something looking at the code so correct me if I'm wrong.

    So it definitely helps to know how stuff is encoded because it can have a huge impact. Sending signed integers can be much more expensive. So it's worth it to see if the values are positive and use the write uint methods if they are.

    Another thing you can and should do with floats in many cases is convert them to integers with a set precision that's 'good enough'. For instance if you are tracking player locations you really don't need more then a couple points of precision, and that's a pretty big savings. Here is the code I use for pretty much all floats. Now this does mean you need to wrap your vectors and quaternions in your own abstraction somehow, but if you are sending a lot of data over the wire it's worth it.

    Code (CSharp):
    1.  
    2.            public float IntToFloat(int i) {
    3.                 return i / 100f;
    4.             }
    5.  
    6.             public int FloatToInt(float i) {
    7.                 return (int)(Math.Round(i * 100, 2));
    8.             }
    9.  
     
    moco2k likes this.
  8. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Thanks for your reply snacktime. Yepp, compression of floats seems to be an efficient optimization measure as floats are usually frequently needed. BTW, another discussion on this can be found in this thread. There is a link to the SlimMath libarary which also provides some functions to pack and unpack floats to ushort (HalfUtilities class).
     
    Last edited: Dec 10, 2015