Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Serialize array of class for networking

Discussion in 'Scripting' started by Defiled, Apr 23, 2018.

  1. Defiled

    Defiled

    Joined:
    Feb 10, 2014
    Posts:
    43
    Hey guys, I'm trying to write an efficient way of sending the player position of everyone on the server to a certain player, now I've accomplished that decently so far by using this.

    Code (CSharp):
    1.     public void massPack( List<uPacket.uPositionObject> data )
    2.     {
    3.         byte[] bytes = new byte[1500];
    4.         BinaryFormatter formatter = new BinaryFormatter ();
    5.         using( MemoryStream ms = new MemoryStream () )
    6.         {
    7.             formatter.Serialize ( ms, data.ToArray () );
    8.             bytes = ms.ToArray ();
    9.         }
    10.         Debug.Log ( bytes.Length );
    11.     }
    This allows me to send around 40 players worth of data in 1 packet, however if I have more than 40 players it'll go over the maximum of 1500 bytes and it wont send properly, so I was thinking of turning it into a foreach loop and after it writes it to the stream it'll check if its >= 1400 bytes length, and if it is then it'll send it and clear the stream before continuing the rest of the packet and then when it's done it'll send that bit too.

    Now I was wondering if that's the most efficient way of sending large amount of data to one client or if there's a better way, and any code provided with explanation would be appreciated!

    Cheers
     
  2. Defiled

    Defiled

    Joined:
    Feb 10, 2014
    Posts:
    43
    I attempted something like this
    Code (CSharp):
    1.         byte[] bytes = new byte[1500];
    2.         BinaryFormatter formatter = new BinaryFormatter ();
    3.         using( MemoryStream ms = new MemoryStream () )
    4.         {
    5.             foreach( uPacket.uPositionObject item in data )
    6.             {
    7.                 formatter.Serialize ( ms, item );
    8.                 bytes = ms.ToArray ();
    9.             }
    10.         }
    11.         Debug.Log ( bytes.Length );
    This would allow me to manipulate the stream whilst its going however the results were bad,
    When I ran the first code it serialized 40 positions and ended up being a total of 1416 bytes
    When I ran the second code it serialized 40 positions and ended up being a total of 7920 bytes

    clearly I did something wrong :(
     
    Last edited: Apr 23, 2018
  3. Defiled

    Defiled

    Joined:
    Feb 10, 2014
    Posts:
    43
    poke, still looking for help
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Rather than trying to guess that 40 positions will fit, I'd serialize all the positions then send the data in 1400~ byte fragments by chopping up the resulting byte array.
     
  5. Defiled

    Defiled

    Joined:
    Feb 10, 2014
    Posts:
    43
    Thanks for the reply, but how would I go about doing that?
    I can't seem to figure out how to make a byte array til a certain amount of bytes length worth
     
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I'd make 1 big byte array, and then from that create a series of smaller byte arrays based on the message size you're needing. Then I'd test how that performs.
     
    Defiled likes this.
  7. Defiled

    Defiled

    Joined:
    Feb 10, 2014
    Posts:
    43
    So the only problem I'm having with that is.. how would the client combine those fragmented byte arrays and even know when a byte[] is being send fragmented?
    I wish there were more document
    I appreciate the help!

    edit: actually if i were to just use a massive array and used QOS.ReliableFragmented would it automatically fragment? I'm gunna give that a go.
     
    Last edited: Apr 24, 2018
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    You could send the length or number of packets in the first few bytes, like a 'size header'.
     
    Joe-Censored likes this.
  9. Defiled

    Defiled

    Joined:
    Feb 10, 2014
    Posts:
    43
    Ah yeah that would work too! cheers
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    My other thought was that you could try to ensure that you never pass a fragmented single piece of position information. If that wasn't tough to do, then the receiver could process the packages and not care if more was coming or not, because they'd be able to process 1 or more byte arrays of the same type..

    Anyways, I think the size at the start is / can be often helpful for certain things of dynamic size in general. :)
    Cheers.
     
    Defiled likes this.
  11. Defiled

    Defiled

    Joined:
    Feb 10, 2014
    Posts:
    43
    Wonder if it would be smart to besides adding the header int to also add a packet id to make sure the same packet is combined anyhow..

    Thanks a lot Methos and Joe-Censored!
     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Oh, maybe.. I suppose that depends on your "channel". That didn't occur to me at first, I was thinking of TCP. heh. If you don't have a reliable sequenced channel, then that would probably be a good idea.