Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Any plans for get/set navmesh data?

Discussion in 'Navigation' started by joshcamas, Mar 26, 2019.

  1. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
    Hello

    The current navmesh implementation is very "Old Unity". Which is to say pretty blackboxy and locked down. Nowadays Unity has gotten really good at making open ended features, such as the SRP, DOTS, and more. With the navigation components this got upgraded a lot more, since it separates the navmesh stuff from the black box that is the scene file. A very good step in the right directiob!

    Is there any plan on making navmesh data accessible? Not just getting the triangulated mesh, but also being able to push data to construct a navmesh?

    With open world games become something Unity is touting (aka megacity), I would imagine this would be very helpful, since there is no way to stitch navmesh chunks, or any way to generate navmeshes on our own. The only reliable method is to simply generate the navmesh for the entire world, and for large worlds stretching for miles this isn't really an option.

    Thank you,
    Josh
     
  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    While they could most definitely improve the runtime build process, I think the problems you are most interested in solving wouldn't be solved by opening up much more.

    A navmesh can only be so big in practice. So eventually you have to navigate between different navmesh's using something other then the navmesh itself. That's just engrained in how recast is architected. Even people using recast directly who have access to the source have to deal with this. And the normal approach is some type of ad hoc bridging system that fits the specific use case. Having access to the full data and source doesn't really open up new ways of handling this. It might make solutions better around the edges or more performant by having the full nav and detail mesh data, but it wouldn't open up completely new approaches to the problem.

    Many studios have integrated recast into their game, I've done it in Unity a couple of times as have others. But at this point with the ability to run queries in jobs the build and loading process is really the last main issue.

    I'm hoping with their new found interest in streaming that they apply that to how they build and load navmesh's. They really should be double buffering the navmesh data, and keeping 100% of the build in jobs not forcing the work to complete on the main thread. If they did that rebuilding at runtime wouldn't impact framerate at all.
     
  3. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
    I disagree, having access absolutely solves this problem, since open worlds are not all streamed in at once.

    In other words, just like how most worlds are split into chunks, split the navmesh into chunks.

    Then, when that chunk is streamed in and activated, stitch the navmesh data together during runtime (current loaded navmesh and the new cell navmesh dataset), and push this new navmesh data.

    In other words, having access to the data let's us do whatever we want, however we want. We can store the data however we want, etc etc.
     
    laurentlavigne likes this.
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    A navigation mesh is bounded. And it uses floats not doubles. There is a practical limit to how big it can be.

    The tiles within a navmesh have neighbor information that lets detour navigate between tiles. Separate navigation meshes would not have that neighbor information.

    That's just how recast works. You can't 'merge' navigation meshes. In the words of the author it's 'nigh impossible'.
     
  5. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
    Please link this quote
     
  6. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
    After looking into it a bit, I'm really not sure what you mean exactly. Astar Pathfinding Project, a unity addon, uses Recast and allows for swapping tiles at runtime.
     
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Astar does not use recast. Recast has become almost a generic term but it's a very specific piece of software (https://github.com/recastnavigation/recastnavigation) and the Astar project is just a port of parts of it's functionality.

    Yes you can swap/rebuild tiles, I never said you couldn't. A tile and a navigation mesh are not the same thing.
     
  8. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
    Alright, then I wish for Unity to add support for swapping/adding/removing tiles, and for us to be able to edit the tile data ourselves. :)
     
    laurentlavigne likes this.
  9. marijnz-klang

    marijnz-klang

    Joined:
    Feb 25, 2019
    Posts:
    6
    Hey, you can stitch navmeshes together with links. Not ideal but works.
     
  10. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
  11. TheMadChemist

    TheMadChemist

    Joined:
    Mar 18, 2015
    Posts:
    10
    I absolutely second that. The current implementation breaks down when you have a world that is large, detailed and dynamic. Every asynchronous update is actually fast, but the collection and rehashing of the entire world causes massive frame-rate issues from calls to NavMesh.AcquireSharedMesh accessing mesh information. It would be nice if we had the ability to rebuild specific tiles where our software design allows us to know which tiles need to be updated and which meshes are relevant. I don't know about Unity's specific implementation but in my own engine, I had built in a modified version of Recast which was capable of this. It would be nice if someone at Unity could take a look and see if this sort of manual update can be added without too much headache.

    As a tip for those trying to use the system as is, depending on the size and complexity you're working with, you may be able to get better performance by pre-baking an initial-state nav mesh. I was able to get vastly improved build times, from several minutes to only a few seconds, by saving the initial worldstate's navigation data and performing updates for dynamic changes. I also noticed an improvement in build times for complete regeneration after loading an initial state as well (from memory allocation maybe?). This is the method I'm using now:

    1. Generate your world in editor, generate nav data
    2. call AssetDatabase.CreateAsset(m_NavMesh, worldNavPathName); on your NavMeshData, save to Resources
    3. On your release build, check if nav mesh is available, m_NavMesh = Resources.Load<NavMeshData>(worldNavPathName);
    4. NavMeshDataInstance m_NavMeshInstance = NavMesh.AddNavMeshData(m_NavMesh)

    Make sure your nav settings are the same and build over the same bounds.
     
  12. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    It does rebuild specific tiles at a time. The whole design of recast is it assumes you build your navmesh ahead of time, and then it detects which tiles were changed when the environment changes and rebuilds those only.

    They could fix it so there is zero main thread time. Double buffer the data, make sure all the work is done in jobs without force completing them which is stalling the main thread.
     
  13. TheMadChemist

    TheMadChemist

    Joined:
    Mar 18, 2015
    Posts:
    10
    Yes, I don't think it's rebuilding every tile since the actual navigation update appears to be very fast.

    Ah ok, I see what you mean. I think we would still need some more control in terms of mesh input in order to handle larger worlds. In my non-unity implementation, I would pass only the world mesh data synced with the bounds of the Recast tile to be updated, and its neighbors. It seems Unity is checking every mesh in the source list per update; while more robust, it is creating unnecessary overhead for what should be a simple job, further compounding the main thread stalls as you increase the overall scene's size and complexity.

    EDIT: After looking closely at what was happening in my test scene, the nav system was for some reason grabbing the mesh attached to the MeshRenderer even though I passed a separate mesh object from the MonoBehaviour. Since the visual mesh was being updated for LOD, it was actually parsing and rebuilding much larger areas of mesh than anticipated. I cleared this up by placing the Mesh object on a separate GameObject (not clear in the documentation how the SourceObject in NavMeshBuildSource relates to the mesh lookup). Now the stutters are less frequent and severe, however, the NavMesh.AquireSharedMesh function is not quite performant, especially when other scripts are accessing and updated mesh data on the same frame. Based on this, it sounds likely that a double buffering scheme can clear these issues up.
     
    Last edited: Apr 8, 2019
  14. jammarman

    jammarman

    Joined:
    Feb 15, 2017
    Posts:
    7
    I've found success generating a navMesh of all the static parts of my level (10km x 10km )with low voxel and radius, exporting to mesh with navmesh.GetTriangulation and then using that mesh as a source at runtime for virtually instant navmesh updates.
     
    joshcamas likes this.
  15. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
    Interesting! I tried this approach and it didn't work for me, but I'm glad it worked for you!! :D
     
  16. fang1994

    fang1994

    Joined:
    Mar 20, 2019
    Posts:
    12
  17. Eck0

    Eck0

    Joined:
    Jun 6, 2017
    Posts:
    48
    hello, I am having problems with the fps drop when rebuilding the navmesh (NavMeshBuilder.UpdateNavMeshDataAsync) and I was wondering if a specific mosaic of the mesh would have a reconstruction way, this way it would avoid the reconstruction of the entire mosaic and it would be almost instantaneous ...
     
  18. fang1994

    fang1994

    Joined:
    Mar 20, 2019
    Posts:
    12
    https://github.com/Unity-Technologies/NavMeshComponents/blob/master/Assets/Examples/Scripts/LocalNavMeshBuilder.cs
    https://docs.unity3d.com/Manual/NavMesh-BuildingComponents.html
    NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, m_Sources, bounds)
    you can assign your own “bounds”
     
    Eck0 likes this.
  19. marijnz-klang

    marijnz-klang

    Joined:
    Feb 25, 2019
    Posts:
    6
    Note for anyone still having issues with this, in Unity 2020.1 `preserveTilesOutsideBounds` got introduced which might avoid the need to combine navmeshes (it does in a project for me) See https://unity3d.com/beta/2020.1b
     
    Thaina, Dinamytes and Eck0 like this.
  20. fang1994

    fang1994

    Joined:
    Mar 20, 2019
    Posts:
    12
    https://github.com/Unity-Technologi...ssets/Examples/Scripts/LocalNavMeshBuilder.cs
    Code (CSharp):
    1.    
    2.  static Vector3 Quantize(Vector3 v, Vector3 quant) {
    3.         float x = quant.x * Mathf.Floor(v.x / quant.x);
    4.         float y = quant.y * Mathf.Floor(v.y / quant.y);
    5.         float z = quant.z * Mathf.Floor(v.z / quant.z);
    6.         return new Vector3(x, y, z);
    7.     }
    8.  
    9.     Bounds QuantizedBounds() {
    10.         // Quantize the bounds to update only when theres a 10% change in size
    11.         var center = m_Tracked ? m_Tracked.position : transform.position;
    12.         return new Bounds(Quantize(center, 0.1f * m_Size), m_Size);
    13.     }
    notice the "Quantize the bounds to update only when theres a 10% change in size", so the "Quantize" is 0.1f * m_Size.
    You can judge the location change range or anything change range, then call UpdateNavMeshDataAsync. Like this:
    Code (CSharp):
    1.    
    2.     Vector3 prePos;
    3.     void Update() {
    4.         if (Mathf.Abs(transform.position.x - prePos.x) > 5 || Mathf.Abs(transform.position.y - prePos.y) > 5) {
    5.             NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, vSources, bounds);
    6.             prePos = transform.position;
    7.         }
    8. }
    My English is pool, just look at the code.
     
  21. fang1994

    fang1994

    Joined:
    Mar 20, 2019
    Posts:
    12
    It may help you
     
    davidrochin likes this.
  22. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    Still no get/setter on navmesh?
    For arbitrary world it's a must.
     
    joshcamas likes this.
  23. FoodFish_

    FoodFish_

    Joined:
    May 3, 2018
    Posts:
    58
    I would like to access underlying tiles of a NavMesh (to access the geometry) any ways to do that? Cheers
     
  24. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    https://docs.unity3d.com/ScriptReference/AI.NavMesh.html

    The newer NavMesh API under the AI namespace is very useful for building NavMeshes at runtime on the fly. You can't access the mesh data itself (such as vertex information), but you can tell it to generate/recreate and assign new NavMeshes when runtime changes are made.
     
  25. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    read only
    Code (CSharp):
    1.  var navMesh = NavMesh.CalculateTriangulation();
    2.     Vector3[] vertices = navMesh.vertices;
    3.     int[] polygons = navMesh.indices