We’ve been using dynamic NavMesh generation for the duration of the project. It ‘just worked’, and our geometry is simple enough that it didn’t appear to be a problem, even though it’s wasteful since our levels are pre-defined.
Now we’re finding that one of our bottlenecks to getting into a match is the time spent on the server generating the NavMesh. Looking at https://dev.epicgames.com/documentation/unreal\-engine/optimizing\-navigation\-mesh\-generation\-speed\-in\-unreal\-engine?application\_version\=5\.7, we believe the section at the bottom for ‘Use Data Chunk Streaming’ sounds like the right approach. But it doesn’t explain the steps needed to make that change.
Given the sensitive nature of the change on a game that’s already going live, we’d like to verify that we are taking the correct approach to optimizing this.
A few specific questions
- Is there much app size impact to storing the pre-built NavMeshes? I assume this is small relative other assets like textures and the actual geometry of the level.
- Do we need to modify the individual NavMesh components to have Runtime Generation: Static? Or is it sufficient to change the Project->Navigation Mesh->Runtime->Runtime Generation method to Static?
- The doc calls out both ‘Static’ and ‘Data Chunk Streaming’, but I don’t see where the ‘Data Chunk Streaming’ setting is, or how it differs from being statically baked.
- Do we need to go through and load each level individually, open it up in the editor, and run Build->Navigation->Build Paths? Or is there a way to do this as a batch update or build it when cooking?
- Are there any tools/best practices for ensuring the NavMesh stays up to date if the geometry of a level is modified so it doesn’t get out of sync? In particular, we’ve had similar issues with lighting not being re-built when a static mesh is changed.
[Attachment Removed]
Steps to Reproduce
Create a project using dynamic NavMesh generation, then switch to pre-built NavMeshes.
[Attachment Removed]
I know we discussed a good amount of this in our call, but want to address it here as well for anyone who finds this later.
Data Chunk Streaming
This is speaking of how we save tiles into ANavDataChunk actors. It is used in World Composition (UE4 level streaming) sublevels so the sublevel would own the relevant navmesh tiles and have them attached to the persistent level’s navmesh actor. We also have a version of this in World Partitioned navmesh where the tiles are stored in chunk actors in the cells. In WP navmesh, there can be multiple data chunk actors per WP cell as the actor tile range is set in the navigation data builder and does not have to be the same as the WP cell size.
You could write some code for building the navmesh and saving it into the data chunk actors (see the WorldPartitionNavigationDataBuilder class for how we do this in a commandlet). There is one caveat that the tiles are built on Recast’s grid, so if you have them in a Level Instance, you would need to ensure that the tiles/LI lined up with the Recast tile grid in your main level. You can call URecastNavMeshDataChunk::MoveTiles to move their position and rotate (we only tested on 90 degree rotations, not sure if other rotations would cause issues) so the Level Instance’s tiles could be re-used in different locations. The tricky part of this is aligning to the Recast grid. You can set it up, but would likely need to work out the math for locations and tile size to ensure they work properly.
The other questions
- There is an overhead for storing your navmesh data to the file. In FNBR, it is around 167MB for the main island. We have introduced some memory optimizations in 5.8 you will want to take as it reduced our memory footprint by 33%. I can get the CLs if you would like to pull them back if the upgrade to 5.8 is a ways out still.
- You should be able to change the project settings for navmesh generation and affect all navmesh actors in your project. There is one BIG caveat to this, and that is that any navmeshes (RecastNavMesh actor in the outliner) that may have been customized over the life of the project will NOT get the update. You could manually remove the navmesh in each level, but I believe there is a way to do this programmatically in a commandlet. This particular wrinkle has impacted us several times in test maps for FN.
- Data Chunk Streaming - see above section
- You should not need to go into each level individually. You can use the ResavePackages commandlet with a flag for building navigation which should do that for you and can even auto-submit when finished if you would like. I can look up specifics if you would like.
- We do a navmesh build each night and monitor it through Horde. This takes a good CL and builds against it. If you do this, the build graph needs to have an entry for compatible changelist added so precompiled binaries can load the asset. Another method is to have automatically update navigation enabled on the project which will build the navmesh as the level or level instance is updated. It should not dirty if nothing affecting the navmesh is changed. So you could change textures, add lighting, spawn points, etc., and the navmesh should not rebuild or dirty itself to bloat CLs being submitted.
-James
[Attachment Removed]