Search Unity

INetworkSerializable w/ CustomMessagingManager

Discussion in 'Netcode for GameObjects' started by Brian-Kryptomon, Apr 24, 2022.

  1. Brian-Kryptomon

    Brian-Kryptomon

    Joined:
    Apr 17, 2022
    Posts:
    17
    Does anyone know if you can leverage these two together?

    I built a solution using RPC but the the scenemanagement and networkprefabs are limiting some of the things I"m trying to do. I'm hoping I can take what I have done and just it down a layer instead of having to redesign the entire thing.

    I don't need any type of syncing its solely messages between client and server.
     
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    I'm not sure on the custom messages but if want to stay at the Rpc level you can have messages of different types, or at least have a Message class where the contents of the message can vary. You need an interface field in the Message class and a type field to know what class the receiver should instantiate and deserialise the data in to.

    I use this setup in a MessageService with a single ServerRpc and ClientRpc and all messages between client and server are handled here, and this avoids having fragmented Rpc calls over different classes.
     
  3. Brian-Kryptomon

    Brian-Kryptomon

    Joined:
    Apr 17, 2022
    Posts:
    17
    @cerestorm yeah I don't really have an issue with that necessarily - my main issue is that with the RPC calls the network objects have to exist on all the scenes and if the server is in one scene and the client is in another they can't seem to communicate. I wanted basically a global network object that could handle the RPC calls but can't seem to figure that out unless I'm missing something obvious.

    The reason for CustomMessagingManager would be that it doesn't require any network objects and I'm free to handle the scenes on the client vs. server independently.

    I saw some stuff about using additive scenes so that the clients can have different scenes than the server but whenever I try to get that working I get network hash for object not found or its looking for a different hash because even though its a singleton in the code it gives it a different hash on different scenes.

    If anyone has code samples on creating global singletons that can handle RPC calls across scenes thats basically what I am looking for.
     
  4. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    That's pretty much how I have it set up, the server sits in its own scene handling client requests while the clients can each be in their own scenes (there is no host). There's a MessageService spawned for each client which calls DontDestroyOnLoad so it survives scene switching.

    The above is achieved with scene management disabled which adds a fair amount of complexity for the server to keep track of where each client is and which network objects should be spawned for their scene.
     
  5. Brian-Kryptomon

    Brian-Kryptomon

    Joined:
    Apr 17, 2022
    Posts:
    17
    Do you put the messaging service on each scene? When I did that they got different network hashes which is what was causing the issue.

    FWIW I figured out how to serialize structs with INetworkSerializable but now I'm having an issue as my CustomMessagingManager is null after I start the server and not exactly sure why.
     
  6. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    No, the message service is spawned on the client as soon as they are connected and persists through all scenes due to a DontDestroyOnLoad call in Awake.

    This is the sequence of events:
    • Server: ConnectionApprovalCallback
      • instantiate message service
    • Server: OnClientConnectedCallback
      • spawn message service on client
    • Client: OnNetworkSpawn of message service
      • send message requesting scene change
    • Server: message service receive message
      • send message to load initial scene
    • Client: message service receive message
      • load initial scene
      • do local intialisation
      • send message scene loaded
    I was initially using custom messages at the start due to no network objects being spawned but I did away with them using the above instead.
     
  7. Brian-Kryptomon

    Brian-Kryptomon

    Joined:
    Apr 17, 2022
    Posts:
    17
    @cerestorm

    Interesting I'll have to take a look at that. I actually was able to get the CustomMessagingManager working for almost every call but now it seems I'm hitting some arbitrary limit on the size of the buffer for writing:


    OverflowException: Writing past the end of the buffer
    Unity.Netcode.NamedMessage.Serialize (Unity.Netcode.FastBufferWriter writer) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.6/Runtime/Messaging/Messages/NamedMessage.cs:14)
    Unity.Netcode.MessagingSystem.SendMessage[TMessageType,TClientIdListType] (TMessageType& message, Unity.Netcode.NetworkDelivery delivery, TClientIdListType& clientIds) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.6/Runtime/Messaging/MessagingSystem.cs:368)
    Unity.Netcode.MessagingSystem.SendMessage[T] (T& message, Unity.Netcode.NetworkDelivery delivery, System.UInt64* clientIds, System.Int32 numClientIds) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.6/Runtime/Messaging/MessagingSystem.cs:481)
    Unity.Netcode.NetworkManager.SendMessage[TMessageType,TClientIdListType] (TMessageType& message, Unity.Netcode.NetworkDelivery delivery, TClientIdListType& clientIds) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.6/Runtime/Core/NetworkManager.cs:1472)
    Unity.Netcode.CustomMessagingManager.SendNamedMessage (System.String messageName, System.Collections.Generic.IReadOnlyList`1[T] clientIds, Unity.Netcode.FastBufferWriter messageStream, Unity.Netcode.NetworkDelivery networkDelivery) (at Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.6/Runtime/Messaging/CustomMessageManager.cs:271)
    BattleManager.SendBattleOverview (BattleEngine.Structs.BattleOverviewStruct battleOverview) (at Assets/Prefabs/BattleManager.cs:243)

    I suspect its the size of the data - no matter what I set the initial size to on the write buffer it always fails:

    Code (CSharp):
    1.  
    2.             using FastBufferWriter writer = new FastBufferWriter(1000000, Allocator.Temp);
    3.             writer.WriteNetworkSerializable<BattleOverviewStruct>(in battleOverview);
    All of my other calls work except this one but it worked before with ServerRPC calls so it must be something specific to CustomMessagingManager.

    The documentation on this is pretty sparse too so not even sure where to start.
     
  8. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    You could try using the the NetworkDelivery.ReliableFragmentedSequenced parameter option when you send the message. I don't know if the Unity transport Payload Size value would also relate to this but may be worth increasing to see if it makes a difference.
     
  9. Brian-Kryptomon

    Brian-Kryptomon

    Joined:
    Apr 17, 2022
    Posts:
    17
    That did the trick! Thanks so much for all your help - I think this should solve my issues in the short term.

    As of right now I don't need to have network objects as I was essentially building a multiple game battle server but in the future we are moving to an open world MMO design so I'll definitely have to play around with the other recommendation you had on dynamic scene / object loading.
     
    cerestorm likes this.