Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved How to use template with enum for reader.ReadValueSafe?

Discussion in 'Netcode for GameObjects' started by darklanx, Sep 7, 2023.

  1. darklanx

    darklanx

    Joined:
    May 21, 2015
    Posts:
    4
    Hi, I'm I have a NetworkEventListener:
    Code (CSharp):
    1. public class NetworkEventListener
    2.     {
    3.         private Dictionary<ushort, MsgEvent> events = new();
    4.  
    5.         public void RegisterEvent(ushort commandType, UnityAction<ulong, SerializedData> callback)
    6.         {
    7.             MsgEvent cmdevt = new();
    8.             cmdevt.commandType = commandType;
    9.             cmdevt.callback = callback;
    10.             events.Add(cmdevt.commandType, cmdevt);
    11.         }
    12.  
    13.         public void OnReceiveNetworkMsg(ulong senderId, FastBufferReader reader)
    14.         {
    15.             reader.ReadValueSafe(out ushort type);
    16.             bool found = events.TryGetValue(type, out MsgEvent networkEvent);
    17.             if (found)
    18.             {
    19.                 networkEvent.callback.Invoke(senderId, new SerializedData(reader));
    20.             }
    21.         }
    22.  
    23.         public class MsgEvent
    24.         {
    25.             public ushort commandType;
    26.             public UnityAction<ulong, SerializedData> callback;
    27.         }
    28.     }
    Where I register the events in both client and server by:
    Client:
    Code (CSharp):
    1. GameNetwork.Singleton.clientEventListener.RegisterEvent((ushort)ServerMsg.PlayerDrawCard, ReceiveDrawCard);
    Server:
    Code (CSharp):
    1.  
    2. GameNetwork.Singleton.serverEventListener.RegisterEvent((ushort)ClientMsg.RequestPlayCard, ReceivePlayCard);
    3.  
    Code (CSharp):
    1.     public enum ClientMsg : ushort
    2.     {
    3.         RequestPlayCard,
    4.  
    5.     }
    6.  
    7.     public enum ServerMsg : ushort
    8.     {
    9.         PlayerDrawCard,
    10.     }
    Where I have to convert ServerMsg and ClientMsg to ushort in order for this to work.

    Is it possible that I can directly use ServerMsg/ClientMsg without converting?
    I tried to change the NetworkEventListener to template class:
    Code (CSharp):
    1. public class NetworkEventListener<T> : System.Enum
    2. ...
    3. public NetworkEventListener clientEventListener<ServerMsg> = new();
    But
    reader.ReadValueSafe(out T type); will have error:
    The type 'T' cannot be used as type parameter 'T' in the generic type or method 'FastBufferReader.ReadValueSafe<T>(out T, FastBufferWriter.ForNetworkSerializable)'. There is no boxing conversion or type parameter conversion from 'T' to 'Unity.Netcode.INetworkSerializable'.

    Not sure how to fix this, I tried to use T: INetworkSerializable but it is no good, which is weird since Enum can be serialized by netcode.
     
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    674
    This might work but I've not properly tested it:
    Code (CSharp):
    1. public class NetworkEventListener<T> where T : unmanaged, Enum
    2. {
    3.     private Dictionary<T, MsgEvent> events = new Dictionary<T, MsgEvent>();
    4.  
    5.     public void RegisterEvent(T commandType, UnityAction<ulong, SerializedData> callback)
    6.     {
    7.         MsgEvent cmdevt = new MsgEvent();
    8.         cmdevt.commandType = commandType;
    9.         cmdevt.callback = callback;
    10.         events.Add(cmdevt.commandType, cmdevt);
    11.     }
    12.  
    13.     public void OnReceiveNetworkMsg(ulong senderId, FastBufferReader reader)
    14.     {
    15.         reader.ReadValueSafe<T>(out T type);
    16.         bool found = events.TryGetValue(type, out MsgEvent networkEvent);
    17.         if (found)
    18.         {
    19.             networkEvent.callback.Invoke(senderId, new SerializedData(reader));
    20.         }
    21.     }
    22.  
    23.     public class MsgEvent
    24.     {
    25.         public T commandType;
    26.         public UnityAction<ulong, SerializedData> callback;
    27.     }
    28. }
     
  3. darklanx

    darklanx

    Joined:
    May 21, 2015
    Posts:
    4
    Thank you so much, this works like a charm.

    Can you explain why adding unmanaged can make the error go away? I don't really get how the error msg is related to unmanaged. Thanks.
     
  4. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    674
    I'm not sure, it looks like as there's no exact signature match and there's a few to choose from it's making a best guess at the one you're trying to use.