The server of my multiplayer game calculates a navmesh path for NPCs. This path is then synced over the network using a serialized Vector3 array obtained through NavMeshPath.corners. However, NavMeshAgent.SetPath and NavMeshAgent.path only allow me to set a NavMeshPath. The reason I want to sync the server generated navmesh path is, to ensure that all clients use the same path for the NPC characters. I could sync the new navmesh position and set it with NavMeshAgent.SetDestination, but that wouldn’t be practical regarding the “same path for all”.
So how would I set the path with the Vector3 array?
Or how can I create a NavMeshPath from the Vector3 array?
Or what’s another way of syncing the server calculated navmesh path?
I did this for my Save & Load system (for NPC nav mesh paths), and I think it works OK, and I hope it might be useful to some other people out there. Or even give people a start on how to do it even better than my version!
It’s a little bit chopped up to fit in the relevant stuff, without too much other guff. Hopefully, the useful bits are all there.
These methods are in a UTILS SCRIPT (for serializing Vector3’s and things)
// you can't directly serialize a Vector3, so make a struct to store the relevant info
[System.Serializable]
public struct SerializedVector3
{
public float x;
public float y;
public float z;
}
// this method converts a Vector3 into a SerializedVector3
public static SerializedVector3 SerializeVector3(Vector3 v3)
{
SerializedVector3 sv3;
sv3.x = v3.x;
sv3.y = v3.y;
sv3.z = v3.z;
return sv3;
}
// this method converts a SerializedVector3 into a Vector3
public static Vector3 DeserializeVector3(SerializedVector3 sv3)
{
Vector3 v3;
v3.x = sv3.x;
v3.y = sv3.y;
v3.z = sv3.z;
return v3;
}
// this method converts a path into an array of SerializedVector3's based on the path corners array.
public static SerializedVector3[] SerializeNavPath(NavMeshPath path)
{
SerializedVector3[] pathCorners = new SerializedVector3[path.corners.Length];
for (int i = 0; i < path.corners.Length; i++)
{
pathCorners[i] = Utils.SerializeVector3(path.corners[i]);
}
return pathCorners;
}
// this method converts the array of SerializedVector3's back into a normal Vector3 array,
// then turns that into a path using the GetCornersNonAlloc method
public static NavMeshPath DeserializeNavPath(SerializedVector3[] sPathCorners)
{
NavMeshPath path = new NavMeshPath();
Vector3[] pathCorners = new Vector3[sPathCorners.Length];
for (int i = 0; i < pathCorners.Length; i++)
{
pathCorners[i] = Utils.DeserializeVector3(sPathCorners[i]);
}
path.GetCornersNonAlloc(pathCorners);
return path;
}
These methods are in my NPC script, for saving and loading the nav mesh path
// this method passes the path into my save & load system
public NPCData PrepareSaveDataForSelf()
{
myNPCData.savedPath = Utils.SerializeNavPath(path);
return myNPCData;
}
// this method takes the saved path, and turns it back into a nav mesh path
public void LoadEntityData()
{
path = Utils.DeserializeNavPath(myNPCData.savedPath);
}
I have the same problem. I want to Calc the path on PC A and send it to B and C. PC A is the only one who is Calc, this is good for performance. But the only way i found out is to change the NavMeshPath.Corner readonly.