Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Nav Mesh runtime bake to only a section of the mesh, not all?

Discussion in 'Scripting' started by dhenion65, Jun 5, 2020.

  1. dhenion65

    dhenion65

    Joined:
    Dec 17, 2019
    Posts:
    21
    I've built a way for the player to modify the terrain height in-game, all is working great - the last piece is to update the nav mesh so that AI's see the new shape of the terrain.

    I've tried NavMeshSurface.BuildNavMesh() and it works, but is slow - and doesn't make sense to rebake the mesh for the entire terrain when only a small portion has been modified.

    So I set NavMeshSurface.center and NavMeshSurface.size - which "works" - the area in that volume is updated, but the rest of the nav mesh is gone.

    Is there any way to re-bake just a portion of the nav mesh?
     
  2. dhenion65

    dhenion65

    Joined:
    Dec 17, 2019
    Posts:
    21
    In searching for ways to do this I found NavMeshBuilder.UpdateNavMeshData which might be a way as it does specify a bounds, but can only find snippets of code here and there - anyone have a good explanation of how to use?

    Also see an example script on the Nav Mesh Components page on github called MeshTool.cs which seems to be a way to move nav mesh verticies - interesting idea, if I could just move the nav mesh verts at the same time I am adjusting the terrain height map I'd be golden.

    Anyone?
    Thanks.
     
  3. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    I know its been a while since this has been asked, but I have an answer on how to use
    NavMeshBuilder.UpdateNavMeshDataAsync
    which, while not the same a
    NavMeshBuilder.UpdateNavMeshData
    should still help.

    Also, another important qualifier, I have not yet tested to see if this works with *modifying* meshes but I plan to work on such a feature in the near future and update this answer accordingly. What I have verified is that this works with adding meshes to an existing surface and updating the navmesh of said surface accordingly.

    Code (CSharp):
    1. using System.Collections; // for IEnumerator
    2. using UnityEngine.AI;         // for navmesh stuff
    3.  
    4. // keep track of NavMeshBuildSources manually
    5. List<NavMeshBuildSource> sources;
    6.  
    7. NavMeshSurface surface; //surface which will include the mesh modified
    8.  
    9. //...
    10.  
    11. void UpdateSurface()
    12. {
    13.     // apply changes to modified mesh -prior- to running this function
    14.     StartCoroutine( UpdateNavMeshAsyncCoroutine(surface) );
    15. }
    16.  
    17. public IEnumerator UpdateNavMeshAsyncCoroutine(NavMeshSurface surface)
    18. {
    19.     var operation = NavMeshBuilder.UpdateNavMeshDataAsync(
    20.         surface.navMeshData,
    21.         surface.GetBuildSettings(),
    22.         sources,
    23.         new Bounds(Vector3.zero, new Vector3(1000,1000,1000)) // set these accordingly
    24.     );
    25.     do { yield return null; } while ( !operation.isDone );
    26.  
    27.     // any logic that you want run -after- the update is applied goes here
    28. }
    29.  
    This should do the trick. Again, I haven't tested this with mesh modification yet, but I believe it will work
     
  4. dhenion65

    dhenion65

    Joined:
    Dec 17, 2019
    Posts:
    21
    Thanks for posting this - just saw it the other day. I've been playing with this and it kinda works but I have the same problem I had before with this - the area in the Bounds is updated and the rest of the nav mesh is gone.

    If I set the bounds to be the entire terrain it works fine - but ideally I'd only update the changed area.

    Also realized that one thing I was doing wrong before was that I had baked the builtin terrain mesh so by adding the NavMeshSurface component I had 2 nav meshes. The rebuild was updating the NavMeshSurface but the agent was using the built in terrain. If I clear the builtin nav mesh it works, except the problem described above.
     
    Last edited: Nov 29, 2020
  5. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    Hey, just a heads up before I continue, I haven't touched my NavMesh code since I last worked on it in September so I'm pretty rusty and I might miss an important detail here or there.

    First off, can you clarify what you mean by 'builtin terrain mesh'? I'm not certain whether you are referring to a GameObject with a Terrain component or just a GameObject with a mesh that you are using as terrain.

    Secondly, when you call
    UpdateNavMeshAsyncCoroutine 
    or
    UpdateNavMeshData
    do you pass the list of all the sources or just put the single, modified mesh in and pass that? The documentation for UpdateNavMeshData states that each source (or mesh) is checked to see if it has changed so that unchanged portions don't get rebaked when they don't need to. However, if you are changing a small portion of a very large mesh this may not help much.

    Thirdly, can you verify that the NavMeshSurface of the builtin terrain and the one from the component are two, different instances? I would just recommend that you change the NavAgents target surface to your new component NavMeshSurface or, better yet, just use the pre existing terrains NavMeshSurface
     
    Last edited: Nov 29, 2020