Search Unity

[NetCode] [ECS] Send list in Rpc?

Discussion in 'NetCode for ECS' started by paolo_simone_enovia, Feb 5, 2020.

  1. paolo_simone_enovia

    paolo_simone_enovia

    Joined:
    Jan 17, 2020
    Posts:
    7
    Hi,

    I would like to send some metadata from server to client after the connection. This metadata doesn't change during the game, so it would make sense to use a Rpc once at the beginning.

    The problem is that the metadata contains a list with a variable number of elements.
    From this thread it seems that the correct way to include a list in a component (and hence in a IRpcCommand?) would be to use a DynamicBuffer, but it's not clear how.
    I have naively tried something like this:
    Code (CSharp):
    1.  
    2. using Unity.Burst;
    3. using Unity.Networking.Transport;
    4. using Unity.NetCode;
    5. using Unity.Entities;
    6. [BurstCompile]
    7. public struct MetadataRpc : IRpcCommand
    8. {
    9.    public int Scalar;
    10.    public DynamicBuffer<IntElement> Numbers;
    11.    public void Serialize(DataStreamWriter writer)
    12.    {
    13.        writer.Write(Scalar);
    14.        writer.Write(Numbers.Length);
    15.        foreach(IntElement n in Numbers)
    16.        {
    17.            writer.Write(n.Value);
    18.        }
    19.    }
    20.    public void Deserialize(DataStreamReader reader, ref DataStreamReader.Context ctx)
    21.    {
    22.        Scalar = reader.ReadInt(ref ctx);
    23.        var length = reader.ReadInt(ref ctx);
    24.        for (int i = 0; i < length; i++)
    25.        {
    26.            Numbers.Add(new IntElement { Value = reader.ReadInt(ref ctx) });
    27.        }
    28.    }
    29.    [BurstCompile]
    30.    private static void InvokeExecute(ref RpcExecutor.Parameters parameters)
    31.    {
    32.        RpcExecutor.ExecuteCreateRequestComponent<MetadataRpc>(ref parameters);
    33.    }
    34.    public PortableFunctionPointer<RpcExecutor.ExecuteDelegate> CompileExecute()
    35.    {
    36.        return new PortableFunctionPointer<RpcExecutor.ExecuteDelegate>(InvokeExecute);
    37.    }
    38. }
    39. public struct IntElement : IBufferElementData
    40. {
    41.    public int Value;
    42. }
    43. class MetadataRequestRpcCommandRequestSystem : RpcCommandRequestSystem<MetadataRpc>
    44. {
    45. }
    46.  
    But I have problems in creating the DynamicBuffer on server... from the documentation seems that it can only be created attached to an entity?
    Probably I'm missing something, but even if I manage to instantiate a DynamicBuffer then I have no idea if it would be actually serialized/deserialized correctly when sent over Rpc?

    So... is there a way to send an Rpc containing a dynamic sized list?
     
  2. Quinnius

    Quinnius

    Joined:
    Jan 29, 2020
    Posts:
    1
    I'm attaching a DynamicBuffer to the IRpcCommand but it never shows up on the client, and I can't find any examples of sending the DynamicBuffer across the network.

    Is this the wrong approach, or just not well documented yet?
     
  3. BrendonSmuts

    BrendonSmuts

    Joined:
    Jun 12, 2017
    Posts:
    86
    The RPC command is a component and has the same restrictions. You cannot have a dynamic buffer reference inside a component. I suggest taking a look at Unity’s new FixedListByteXXX structures in Unity.Collections. These are in place arrays that can be stored inside components. Be warned they are not resizable and used incorrectly can create very large components as the buffer they wrap around is inside the structure and not allocated on the heap. If you have a fixed upper limit on the size these should work for you.
     
    paolo_simone_enovia likes this.
  4. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    28
    Thanks for the hint with FixedListByte, quite usefull :)
    I got the weird bug though , that when sending an entity as rpc with a component that has a FixedListByte512 inside, it arrives with 0 elements in it. I checked my system sending it, it correctly reported that it's sending 181 elements.

    @BrendonSmuts did you ever had something like that ?
     
  5. BrendonSmuts

    BrendonSmuts

    Joined:
    Jun 12, 2017
    Posts:
    86
    I have not ran into any issue sending fixed list data through the RPC system no. Perhaps you can paste your code around the serialization/deserialization logic. Chances are there is some bug in your own process.
     
  6. MarcelArioli

    MarcelArioli

    Joined:
    May 31, 2014
    Posts:
    28
    Ah you're absolutely right !
    I didn't bother writing a custom serialization logic, and just looked at the one unity is autogenerating : it couldn't auto create serialization for that fixedlist member.

    Thanks for your input
     
  7. skiplist

    skiplist

    Joined:
    Nov 9, 2014
    Posts:
    47
    A small tip if like me you are too lazy to do your own serialization code: serialization for FixedStringXXX is autocreated which you can (ab)use to send raw data :)