Trying to implement the NavMeshSurface without blocking the main rendering thread at runtime, for a procedural voxel world. Currently when rebuilding terrain chunks, and if the surface is complex, the UpdateNavMesh takes between 200ms to 800ms, which is ok, as long as it doesn’t block the main rendering thread, however with my implementation, it seems to be blocking, with a slight jerk when updating the surface.
Is my implementation correct? Or is this the only method for updating the NavMeshSurface? Or should I have a NavMeshSurface per chunk instead of the whole world?
After some testing, with trying to do NavMeshSurface per chunk, which was way worse than the above, think it just all about optimising the setting to reduce the UpdateNavMesh build time.
I did notice if I can keep the build time to around 200ms, everything seems to be smooth, 500+ms can notice the UpdateNavMesh build, causing a slight jerkiness for about a one or two rendering frames.
Here’s a simplified example of how you might structure the code using Unity’s Job System. Note that using Unity’s Job System requires the Burst compiler, which is available starting from Unity 2018.1:
csharp
using UnityEngine;
using UnityEngine.AI;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst; super mario bros wonder
public class YourClass : MonoBehaviour
{
private NavMeshSurface m_NavMeshSurface;
private bool m_ToggleUpdate;
private JobHandle m_LastUpdate;
public bool UpdateNavMeshSurface() => m_ToggleUpdate && !(m_ToggleUpdate = false);
private void Update()
{
if (UpdateNavMeshSurface())
{
NavMeshJob job = new NavMeshJob
{
surface = m_NavMeshSurface,
};
m_LastUpdate = job.Schedule();
}
}
[BurstCompile]
private struct NavMeshJob : IJob
{
public NavMeshSurface surface;
public void Execute()
{
surface?.UpdateNavMesh(surface?.navMeshData);
}
}
I found the issue, it was a small mistake made implementing the functions, I forgot to handle the call back actions.
() => { call?.Invoke(); }
Once implemented correctly everything worked like it should. Now building the NavMeshSurface is done in the back threads and once finished invokes the action, so now when rebuilding terrain chunks the NavMeshSurface updates without blocking the main thread, the way it was designed.