Search Unity

Question Help with INetworkSerializable (arrays)

Discussion in 'Netcode for GameObjects' started by GuirieSanchez, Dec 20, 2022.

  1. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    I have a bunch of parameters (int, bool, string, float, vectors, etc.) and also arrays and lists that I want to pass through a struct.

    I was checking the documentation here and it seems pretty straightforward when it comes to single parameters:
    upload_2022-12-20_18-53-56.png
    As far as I understand this, if I have, let's say, 30 public parameters in the struct, then on the NetworkSerialize, for each of them, I have to make a reference with the serializer. For instance:
    Code (CSharp):
    1. serializer.SerializeValue(ref param1);
    2. serializer.SerializeValue(ref param2);
    3. serializer.SerializeValue(ref param3);
    4. serializer.SerializeValue(ref param4);
    5. serializer.SerializeValue(ref param5);
    6. serializer.SerializeValue(ref param6);
    7. serializer.SerializeValue(ref param7);
    8. // etc.
    9. serializer.SerializeValue(ref param30);
    Now, when it comes to using arrays on a struct, they have this example:
    upload_2022-12-20_18-59-7.png

    But I don't understand it perfectly. If the array contains both single parameters and also arrays, does the NetworkSerialize need to look like this? (containing both):
    Code (CSharp):
    1. public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    2.     {
    3.         serializer.SerializeValue(ref param1);
    4.         serializer.SerializeValue(ref param2);
    5.         serializer.SerializeValue(ref param3);
    6.         serializer.SerializeValue(ref param4);
    7.         serializer.SerializeValue(ref param5);
    8.         serializer.SerializeValue(ref param6);
    9.         serializer.SerializeValue(ref param7);
    10.         // etc.
    11.         serializer.SerializeValue(ref param30);
    12.         // +
    13.  
    14.         // Length
    15.         int length = 0;
    16.         if (!serializer.IsReader)
    17.         {
    18.             length = Array.Length;
    19.         }
    20.  
    21.         serializer.SerializeValue(ref length);
    22.  
    23.         // Array
    24.         if (serializer.IsReader)
    25.         {
    26.             Array = new int[length];
    27.         }
    28.  
    29.         for (int n = 0; n < length; ++n)
    30.         {
    31.             serializer.SerializeValue(ref Array[n]);
    32.         }
    33.     }
    Also, I don't completely understand the role of the
    public int[] Array;
    here. It's supposed to be your array. What if you have 10+ arrays of different types, do you have to replicate the
    Code (CSharp):
    1. // Length
    2.         int length = 0;
    3.         if (!serializer.IsReader)
    4.         {
    5.             length = Array.Length;
    6.         }
    7.  
    8.         serializer.SerializeValue(ref length);
    9.  
    10.         // Array
    11.         if (serializer.IsReader)
    12.         {
    13.             Array = new int[length];
    14.         }
    15.  
    16.         for (int n = 0; n < length; ++n)
    17.         {
    18.             serializer.SerializeValue(ref Array[n]);
    19.         }
    for each array? It seems counterintuitive to make it like that, so I'm almost sure I'm misunderstanding this.

    Lastly, I'm not completely sure how to update the information inside the struct. On the docs, they show
    Code (CSharp):
    1. MyServerRpc(
    2.             new MyComplexStruct
    3.             {
    4.                 Position = transform.position,
    5.                 Rotation = transform.rotation
    6.             }); // Client -> Server
    but I imagine it can get real complicated having to update 30+ parameters and arrays like this
    Code (CSharp):
    1. MyServerRpc(
    2.             new MyComplexStruct
    3.             {
    4.                 param1 = value1,
    5.                 param2 = value2,
    6.                 param3 = value3,
    7.                 param4 = value4,
    8.                 param5 = value5,
    9.                 param6 = value6,
    10.  
    11.                 // etc.
    12.                 param30 = value30,
    13.  
    14.                 // then arrays
    15.                 for (int i = 0; i < myArray1.Length; i++)
    16.                    {
    17.                         myArray1[i] = valueArray1[i];
    18.                    }
    19.  
    20.                 for (int i = 0; i < myArray2.Length; i++)
    21.                    {
    22.                        myArray2[i] = valueArray2[i];
    23.                    }
    24.                 // etc.
    25.  
    26.  
    27.                  }); // Client -> Server
    Thank you
     

    Attached Files:

  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,970
    Not sure if NGO supports this but the immediate solution to this would be to create a ArrayStruct that serializes just the array, possibly as a generic type, and then you'd use that ArrayStruct as one or more fields in your custom struct. To serialize you simply forward the calls to the methods in ArrayStruct.
     
    GuirieSanchez likes this.
  3. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    I did it the ugly way. I'm using a separate struct just for arrays (where I declare the 10 arrays I want to pass), and the way it's serializing is by having them referenced throughout:
    Code (CSharp):
    1. public struct ArrayStruct : INetworkSerializable
    2. {
    3.  
    4.     public Vector3[] array1;
    5.  
    6.     public int[] array2;
    7.  
    8.     public int[] array3;
    9.  
    10.     public int[] array4;
    11.  
    12.     public bool[] array5;
    13.  
    14.     public bool[] array6;
    15.  
    16.     public int[] array7;
    17.  
    18.     public int[] array8;
    19.  
    20.     public int[] array9;
    21.  
    22.     public FixedString64Bytes[] array10;
    23.  
    24.  
    25.     public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    26.     {
    27.         // Length
    28.         //int length = 0;
    29.         int array1Length = 0;
    30.         int array2Length = 0;
    31.         int array3Length = 0;
    32.         int array4Length = 0;
    33.         int array5Length = 0;
    34.         int array6Length = 0;
    35.         int array7Length = 0;
    36.         int array8Length = 0;
    37.         int array9Length = 0;
    38.         int array10Length = 0;
    39.  
    40.         if (!serializer.IsReader)
    41.         {
    42.             array1Length = array1.Length;
    43.             array2Length = array2.Length;
    44.             array3Length = array3.Length;
    45.             array4Length = array4.Length;
    46.             array5Length = array5.Length;
    47.             array6Length = array6.Length;
    48.             array7Length = array7.Length;
    49.             array8Length = array8.Length;
    50.             array9Length = array9.Length;
    51.             array10Length = array10.Length;
    52.         }
    53.  
    54.         serializer.SerializeValue(ref array1Length);
    55.         serializer.SerializeValue(ref array2Length);
    56.         serializer.SerializeValue(ref array3Length);
    57.         serializer.SerializeValue(ref array4Length);
    58.         serializer.SerializeValue(ref array5Length);
    59.         serializer.SerializeValue(ref array6Length);
    60.         serializer.SerializeValue(ref array7Length);
    61.         serializer.SerializeValue(ref array8Length);
    62.         serializer.SerializeValue(ref array9Length);
    63.         serializer.SerializeValue(ref array10Length);
    64.  
    65.         // Array
    66.         if (serializer.IsReader)
    67.         {
    68.             array1 = new Vector3[array1Length];
    69.             array2 = new int[array2Length];
    70.             array3 = new int[array3Length];
    71.             array4 = new int[array4Length];
    72.             array5 = new bool[array5Length];
    73.             array6 = new bool[array6Length];
    74.             array7 = new int[array7Length];
    75.             array8 = new int[array8Length];
    76.             array9 = new int[array9Length];
    77.             array10 = new FixedString64Bytes[array10Length];
    78.  
    79.         }
    80.  
    81.         for (int n = 0; n < array1Length; ++n)
    82.         {
    83.             serializer.SerializeValue(ref array1[n]);
    84.         }
    85.         for (int n = 0; n < array2Length; ++n)
    86.         {
    87.             serializer.SerializeValue(ref array2[n]);
    88.         }
    89.         for (int n = 0; n < array3Length; ++n)
    90.         {
    91.             serializer.SerializeValue(ref array3[n]);
    92.         }
    93.         for (int n = 0; n < array4Length; ++n)
    94.         {
    95.             serializer.SerializeValue(ref array4[n]);
    96.         }
    97.         for (int n = 0; n < array5Length; ++n)
    98.         {
    99.             serializer.SerializeValue(ref array5[n]);
    100.         }
    101.         for (int n = 0; n < array6Length; ++n)
    102.         {
    103.             serializer.SerializeValue(ref array6[n]);
    104.         }
    105.         for (int n = 0; n < array7Length; ++n)
    106.         {
    107.             serializer.SerializeValue(ref array7[n]);
    108.         }
    109.         for (int n = 0; n < array8Length; ++n)
    110.         {
    111.             serializer.SerializeValue(ref array8[n]);
    112.         }
    113.         for (int n = 0; n < array9Length; ++n)
    114.         {
    115.             serializer.SerializeValue(ref array9[n]);
    116.         }
    117.         for (int n = 0; n < array10Length; ++n)
    118.         {
    119.             serializer.SerializeValue(ref array10[n]);
    120.         }
    121.     }
    122. }
    I know it's ugly and to some extent, it doesn't make much sense to have it that rigid, but, unfortunately, I couldn't come up with a generic solution like the one you suggested. Let me know if you have a suggestion to improve it or a hint towards having it generic so that it can be reused.
     
    avidpl likes this.