Hi everyone,
We’re facing a challenge with NavMesh generation in a LevelStreaming setup, and I’d appreciate any input or guidance.
Context
Our project uses Level Streaming to split the world into modular sublevels. We also use a static RecastNavMesh. However, some sublevels are intentionally overlapping in world space — for example, different dungeon variants occupying the same coordinates and being loaded/unloaded at runtime depending on gameplay logic.
This leads to issues with NavMesh generation. Since Recast considers all geometry present in the world when generating the NavMesh, overlapping geometry results in invalid or broken navigation data in the overlapping zones.
Our Current Solution
We’ve built a workflow where each streaming sublevel is opened individually in the editor and we manually run BuildPaths. This generates a RecastNavMesh specific to that sublevel, as well as a corresponding RecastNavMeshChunk.
At runtime, the tiles from these NavMesh chunks are dynamically attached to or detached from the main RecastNavMesh on the PersistentLevel, depending on whether the corresponding sublevel is streamed in or out. This allows us to keep only the navigation data relevant to the currently loaded geometry active.
To support this, we had to:
- Enable generation of a NavMesh chunk for the PersistentLevel when running BuildPaths from an opened streaming sublevel. By default, chunk generation didn’t work in that context.
- Patch the engine to correctly handle AttachTiles and DetachTiles, so that tiles from the sublevel’s chunk can be dynamically added to or removed from the main RecastNavMesh at runtime.
- Increase the internal REGISTRATION_QUEUE_SIZE to avoid runtime warnings and registration failures when multiple navmeshes are being loaded simultaneously.
Problems with This Approach
- It required non-trivial engine modifications.
- At runtime we get several warnings:
- NavData RegistrationFailed_AgentAlreadySupported specified agent type already has its navmesh implemented
- Navigation System: registration queue full!
- Overall, it feels like we are fighting the system — like we’re doing something fundamentally wrong.
Question
Is there a better or more canonical way to handle streaming levels with overlapping geometry and modular static NavMesh generation?
Specifically:
- Is our idea of pre-generating NavMesh chunks per sublevel and managing them manually at runtime a good direction, or are there recommended alternatives?
- Can we safely support overlapping geometry in streaming levels with the navigation system?
- Are the warnings above indicative of a misconfiguration, or are they harmless?
Any insights on whether this setup is sustainable long-term — or if there are more robust, supported ways to handle static NavMesh generation for overlapping streamed sublevels — would be very helpful.
Thanks!