How to build navmesh for dynamically sized procedural level

I’m building a level generator that makes levels of a generally rectangular shape, but of a dynamic size along the X & Y axes. I have a blueprint that scales the navmesh volume actor in the X & Y so that it encompasses the walkable ground (including enough buffer in the Z direction), but it does not seem to be rebuilding the navmesh during runtime upon level load (no green area with navigation visualization on and no response to input), even though runtime rebuilding is enabled. I’m guessing the runtime rebuiliding only supports the moving or scaling of actors within the navigation volume, and not scaling of the navigation volume itself. So how would I go about handling navigation for a procedural level like this?

1 Like

I’ve had a quick look at the code and it seems we don’t support runtime navigation bounds scaling. Here are some thing you can do:

  • you can have one big volume encompassing the whole possible generated level space. This should not have a big impact on navmesh generation time.
  • you can expose UNavigationSystem::OnNavigationBoundsUpdated and call it with the scaled ANavMeshBoundsVolume. This should work, but I’m not 100% sure it will. Let me know if it does if you decide of this route.
  • you could try streaming NavMeshBoundsVolume in. Again, not sure if it will work since we don’t use this approach internally.

Cheers,

–mieszko

I went ahead and exposed UNavigationSystem::OnNavigationBoundsUpdated, and called it from my level generator blueprint. Once I changed the navigation bounds volume to Movable it worked. So, thanks!

I should mention that the function has a comment on it that says that if it’s going to be used at runtime then it should probably be optimized, and it does take a little bit to generate at game start. So now you know that some people are indeed going to be using it at runtime.

Thanks again,
Eric

There’s not much performance to be gained in your use case. Building navmesh once on level load/start can go with what’s currently there, you do it once and you’re fine for the rest of the level. If we wanted to use this in a frequent-rebuilding scenario then it could use some more attention.

–mieszko

Can you please provide some insight into how you scaled the ANavMeshBoundsVolume at runtime ? I’m in the same boat but can’t figure out how to scale the brush / volume. I’ve already isolated the object in code. Thanks!

Sorry for the delayed response. I did the actual scaling in Blueprints. I exposed the UNavigationSystem::OnNavigationBoundsUpdated function to Blueprints, and called SetActorScale3D on the NavMeshBoundsVolume in my level generation blueprint, and then called the OnNavigationBoundsUpdated node afterwards.

Streaming volumes (i add one per level chunk) works too.

@MieszkoZ

UNavigationSystem::OnNavigationBoundsUpdated

this doesn’t work in c++, I mean it works but the other way round so if you re-scale your navMeshVolume in code and hit play nothing happens but as soon as you stop the play mode and get back in to editor mode changes get applied, Can anyone tell me if there is any performance or memory footprint if I create massive navigation mesh ?
I have procedural dungeon generator done in c++ from my portfolio and the thing is that entire level size can be changed at run time witch means I will either have to scale nav mesh volume witch is impossible at run time or I will have to create nav mesh volume big enough to cover all possible level sizes but what if I create nav mesh approx. 10000x 10000y 500z but my map will be only 100x 100y and 500z at the time ? will this have impact on game performance or will it have memory footprint etc. or it will only allocate as much memory as needed ?

apparently one option is to use a Recast Navmesh

No. The right way is to use nav invokers.
But this was originally from a point in time where about 1/4 of the current tools existed.

1 Like

Hey, do you think there are better tools currently to spawn navmesh in target areas surrounding the player?

The thing with Nav Invokers is that they do not require you to craft and cusromize nav meshe data.

They work automatically based on what is placed in the level and the settings for it (can character walk on, etc).

The use case for those is dynamic terrain/automatic generation, runtime changes etc.

Nav mesh as a custom edited thing is useful for closed projects where things wont change.
Say something like an endless runner that spawns/respawns pieces which are standard - and can use the memory reduction you get from precalculating the mesh instead of having it generate at runtime.

2 Likes

Found a solution to the problem
Disclaimer: I am still using UE4, so maybe this was fixed in UE5, I don’t know, but I doubt it

Invokers are a different thing that serve a completely different purpose than what asked in this thread, they are useful for huge worlds where it’s impossible to build the whole navmesh at once.

It seems that the UBrushComponent’s bounds inside ANavMeshBoundsVolume is not updated correctly when scaling the actor at runtime, this can be fixed by setting the bounds directly

UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());

ANavMeshBoundsVolume* BoundsVolume = GetWorld()->SpawnActor<ANavMeshBoundsVolume>();
BoundsVolume->GetRootComponent()->Bounds = YourBounds;
NavSys->OnNavigationBoundsUpdated(BoundsVolume);
1 Like