World Partitioned NavMesh support for level modifications, without full rebake

Hi,

I got a few questions/feature requests for the World Partitioned Navmesh.

Disclaimer: We are currently on 5.4, as far as I can tell these issues haven’t been addressed in 5.5 or 5.6, but please correct me if I am wrong.

First and most important request, is support for iterative level design. Only thing I could find was this from a year ago [Content removed] has anything been added to the roadmap yet?

We are working on a large world and would like to use WP navmesh, but as it is not viable to rebake the entire nav mesh before every commit (or entering PIE), we haven’t found a good way to make it usable during development, without getting artefacts, from small or big changes.

What is the best approach to temporarily detach actors from a baked navmesh? I.e. if we move a static mesh in level editor, we would like the nav mesh to be dynamically regenerated at runtime, after nav chunk load, at both the old and new location.

Next issue we encountered, was nav persistency during respawn. We reload all streamed in levels, but since this is not a visibility change, it dirties everything. My current approach is to compare all unregister/register events send to the nav system, and only forward the unmatched, This is cumbersome, but works for now.

Is there a way to tell the nav system, to treat those reloads the same way as visibility changes?

Baking the entire world is very slow. We do have a huge world, but seems that a lot of the bake time is spent on loading areas with no nav bounds. Is there a way to optimize this? And is there any simple way to rebake individual chunks? rather than doing the full rebake. Currently nav bounds volumes are spatially loaded, to prevent complaints about fixed pool size being too small. But I am not sure if we should have those always loaded instead?

Finally the debug rendering of navmesh is very slow for large areas, due to expensive bounds calculation, and a lot of vertex duplication in the nav renderer component. I have made a stripped down debug renderer, but would rather not spend more time on this, if you have something scalable in the workings.

Is there any plans for optimizing this? (or am I doing something wrong?)

Hope you can give us some pointers on how to make the WP Navmesh viable during production.

And let me know if you would rather have the post split up into individual questions :slight_smile:

/Jannek

There has not been any big changes in support for WP navmesh. It is still experimental and follows the same build process. We have long term plans to address some of the issues in WP navmesh, but I do not have an ETA of when those will occur.

There is no method for moving the actor and then having the navmesh rebuild that area easily. You could call to dirty the tiles in the the actor’s bounds on BeginPlay so that the system would attempt to rebuild the tiles. It would work during the PIW session, but the baked portion of the navmesh (and octree) would still reflect what was made with the WP navmesh builder.

Most of the navmesh building time is loading the various sections of the world as you have found. Our advice is to use the largest Navigation Data Builder Loading Cell Size for the build machine to handle. I remember seeing something recently in our JIRA about WP navigable bounds in the builder and it may have been a PR for better results. I am not sure if it was investigated yet.

We reload all streamed in levels

Are you using sub-levels like UE4 World Composition level streaming? Or is this dynamically loading Level Instances into the world rather than having the placed in the level?

We do not have any plans for improving the navmesh debug rendering at this time. I do not believe we have experienced a large performance hit from having it running. At least none that has caused it to be brought to the engine team’s attention from FNBR or Lego FN. I know our QA had found some jitter in the navmesh display at very large distances, but the issue has not been closed in our JIRA.

-James

Thanks for the quick reply.

Well that’s a shame. Has octree data been added to the bake in recent versions?

Using the largest Navigation Data Builder Loading Cell Size, seemed to clog up `FAsyncLoadingThread::ProcessAsyncLoading`, but it helped to let the cell iterator load all the chunks first, and then do the nav gen on the whole thing after.

We are using World Partitions, with a few Level Instances, but those are not related to the large nav areas. Our reload approach is to first disable streaming sources, then call `SetShouldBeLoaded(false)` on relevant `ULevelStreamingDynamic` from the world. And back to true again, after everything has been unloaded and game states rolled back.

Regarding the slow debug rendering, it is largely caused by `UNavMeshRenderingComponent` doing a full refresh on any nav data modification + `FNavMeshSceneProxy` appending a full copy of the nav mesh debug vertex data per NavArea to the vertex buffer. But we have a stripped down version to use for now, so not urgent for us.

Would you be able to capture and share an Insights recording with the navmesh rendering slowdown in editor? As well as any relevant settings so we can repro and check perf. We have not been using WP navmesh for internal projects, so there is certainly potential that we have not seen the issue, at least not to the extent you have experienced.

Loading is the biggest slowdown we have seen in our WP navmesh builder testing. I know that there are efforts underway to improve loading and streaming perf. The time for WP navmesh building is something we will look into when we begin more dev on WP navmesh.

Octree data is not serialized. It was something that I had remembered being posited at one time, but it was not added to the engine. The extra memory footprint did not seem to outweigh the cpu cost for gathering data.

Do you know how large your map is roughly? Is it 25km^2? Larger? How many tiles are you displaying at a given time? The largest map we build navigation for is FNBR, so it might be that the cost of navmesh debug rendering is not something we have seen just due to the size of the level.

I have been diving into this and found something like 50ms for the NavMeshRenderingComp in a WP map with ~12k active tiles. Do you know what the times you were seeing for it when it was rebuilding?

We do not have anything planned currently to address this. I have brought it forward to some others on the team to discuss, but I cannot even assign it a priority level quite yet for us. If you do work on changing it, we would be curious to see the improvements and changes made.

-James

Sorry I accidentally posted my reply to the original question.

Just to sum up my questions:

Having the octree data from the WP builder, would solve a lot of things. From what version has this been added?

What would be the optimal way to reload the WP world (no GC), without causing actors/components included in the base navmesh to dirty the world? I am already duplicating the chunk data, to prevent the multi layer bug/“Turn on GC” warning. But our current approach prevents the “is part of base navmesh” check, since it isn’t due to a visibility change.

Hi, sorry for the late reply.

I have a made a lot of local modifications, so giving a usable dump is a bit cumbersome. But as mentioned this is largely due to no caching, of vertex data (any tile update requires a full refresh) and some redundant duplication and offsetting when pushing it all to the vertex buffer in the `FNavMeshSceneProxy`. Getting rid of the vertex duplication shaves a lot off, but with no caching gathering the nav data still takes several ms for large areas.

You mentioned octree data being in the bake as well. I can’t find any info on this. Has this been added recently?

Current most noticeable slowdown is in an area with ~4k tiles. The area is not optimized for nav yet, and we are not on 5.6 yet, so no `bRasterizeAsFilledConvexVolume` on our ISMs.

As mentioned the rendering part is not that expensive, it is the full refresh whenever a single nav modifier is moved, which happens pretty much every frame, that makes it expensive. This can easily go above 30ms.