Search Unity

  1. Unity 2019.4 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  3. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

Serializing NavMeshPaths to sync NavAgents across the network

Discussion in 'Navigation' started by sonderistic, Jun 4, 2019.

  1. sonderistic

    sonderistic

    Joined:
    Jan 4, 2017
    Posts:
    6
    Hello, as the title states, I'm trying to serialize NavMeshPaths so I can send it through the network. However, the class doesn't seem to support serialization. Has anyone accomplished this? The reason for this is so I can calculate paths on the Server and merely distribute the paths to the clients who will set their nav agents with the correct paths.

    An alternative to this which I am aware of is to instead send the destination to the clients but, I'm pretty sure that there is bound to be some discrepancy in the paths the AIs take. I also would not like to sync their positions because I wish to use root motion for each client (I've heard that root motion and network transform / lerping do not play well together).

    I've spent the better part of the month trying to find a solution to this issue. Any help would be greatly appreciated. Also, below is the error when trying to serialize a NavMeshPath.



    SerializationException: Type 'UnityEngine.AI.NavMeshPath' in Assembly 'UnityEngine.AIModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
    System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (System.RuntimeType type) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.FormatterServices+<>c__DisplayClass9_0.<GetSerializableMembers>b__0 (System.Runtime.Serialization.MemberHolder _) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.FormatterServices.GetSerializableMembers (System.Type type, System.Runtime.Serialization.StreamingContext context) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo () (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize (System.Object obj, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.Formatters.Binary.ObjectWriter objectWriter, System.Runtime.Serialization.SerializationBinder binder) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize (System.Object obj, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.Formatters.Binary.ObjectWriter objectWriter, System.Runtime.Serialization.SerializationBinder binder) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write (System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo objectInfo, System.Runtime.Serialization.Formatters.Binary.NameInfo memberNameInfo, System.Runtime.Serialization.Formatters.Binary.NameInfo typeNameInfo) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize (System.Object graph, System.Runtime.Remoting.Messaging.Header[] inHeaders, System.Runtime.Serialization.Formatters.Binary.__BinaryWriter serWriter, System.Boolean fCheck) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers, System.Boolean fCheck) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
    ZombieServer.SerializeForNetwork (System.Object obj) (at Assets/_Testing/Bryan/BRB Zombies/Scripts/ZombieServer.cs:67)
    ZombieServer.SendUpdatedPathToClients (System.UInt16 zombieNetID, UnityEngine.AI.NavMeshPath path) (at Assets/_Testing/Bryan/BRB Zombies/Scripts/ZombieServer.cs:83)
    ZombieBrain.Update () (at Assets/_Testing/Bryan/BRB Zombies/Scripts/ZombieAI/ZombieBrain.cs:47)
     
  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,829
    The approach isn't necessary. You could serialize the corners and then issue new path requests along those on the client, but pathfinding itself is mostly deterministic. Sending destinations works fine.

    But crowd handling is not deterministic so that is really the main issue with your approach. You can't have client side pathfinding using the built in agents and have it be deterministic.

    The right approach here if your server is calculating paths is to just send position updates and use network interpolation on the client. Your client side characters won't be agents, just a transform and maybe a collider if needed and with a script moving them directly.
     
unityunity