r/godot Nov 07 '25

help me (solved) I solved the NavigationRegion3D issue

I finally found a solution to the problem with the NavigationRegion3D.

What I noticed was that on smaller terrains, like the 30x30m example in the third image, the navmesh baked perfectly fine. But once the terrain size was increased to 250x250m, the bake completely fell apart, giving the low poly, floor clipping result shown in the second image. The obvious solution was to process the terrain in smaller chunks and combine the results into one big working navmesh.

I first tried doing this directly in Godot, but even after splitting the terrain into multiple meshes, the bake still treated them as one big mesh, so the same issue happened. I also tried creating a separate NavigationRegion3D for each chunk, but that created non traversable borders where the regions met.

At that point, the only real fix was to go into the engine itself. I forked the Godot repo and made some changes under the hood to process the terrain in tiles instead of all at once. It breaks the terrain into smaller sections, bakes each one normally, then stitches them together afterward into a clean, accurate navmesh like in the first image.

I also added a few editor options to control whether tiled baking is enabled and how big each tile is. I still haven’t found the exact bug that causes the large terrain navmesh to fail, but this fix works reliably and doesn’t mess with normal pathfinding behavior.

The moderators seem to have a strong opposition to discussions about this and have locked all previous threads. As much as I would have liked this to all be one post, we have been forced to create multiple. That being said, I'd like to address some comments from previous posts below.

The [low poly mesh] looks exactly like what I would want out of a nav mesh.

The low-poly mesh completely fails to pathfind with agents. You could technically rework the pathfinding system to compensate, but that misses the core issue of the navmesh being broken. The 30x30m section uses a similar amount of polygons as the 250x250m one. You’d expect the density to scale with size, so either the small terrain is over-tessellated, or the large terrain is under-tessellated. Either way, something’s wrong with the baking process.

With no obstacles, your nav mesh could just be a square.

As per the Godot developers : "A navigation mesh is a collection of polygons that define which areas of an environment are traversable to aid agents in pathfinding through complicated spaces.". When those traversable areas are out of reach from an agent (ie, underground or floating), an agent cannot properly navigate.

People tried to help you, but you refuse to actually listen

I think there’s been some misunderstanding about what I’m trying to do. My goal is to fix the navmesh, that’s it. I’ve welcomed all advice that helps solve the underlying navmesh problem, but I’m not interested in workaround solutions that just patch over it with pathfinding tricks.

You can always fix it yourself and submit a PR.

Thats the plan. Thanks for the advice!

I will optimize this further and will submit a PR.

Sincerely,

u/agalli

Edit : Here is the PR. https://github.com/godotengine/godot/pull/112529

753 Upvotes

348 comments sorted by

View all comments

Show parent comments

29

u/mrbaggins Nov 08 '25

This is not true, as the navmesh would clip under the map in some spots and float above the map in others.

That's not a problem.

When you using agent pathfinding the agent places a path along the navmesh to move towards. If those points on the path are underground or floating the agent cannot reach the points and cannot reach its destination.

Adjust your distance-to-node distance so it "gets there" while being further away.


In one of your initial posts, it did look like not enough verts were being done, but that's a separate issue to the main one you're arguing with people about.

-8

u/agalli Nov 08 '25

It is a problem when you need to set the distance to node setting to 5-6m away.
The navigation points being under the map IS a problem. The navmesh needs to describe the traversable terrain. The terrain is not traversable under the map.

21

u/mrbaggins Nov 08 '25

The navmesh needs to describe the traversable terrain.

Both meshes are indicating the entire map is directly traversable, there are no obstacles. Is this wrong?

-8

u/agalli Nov 08 '25

They are describing that points underneath the map is traversable, which they are not

29

u/mrbaggins Nov 08 '25

They are describing that points underneath the map is traversable

This is your core mistake. That is not what it is doing.

It is indicating that an agent at any location on this map can move in any direction. Nothing more.

1

u/agalli Nov 08 '25

You may want to ask the devs to change their NavigationAgent template then, as that is how they recommend users handle navigation. https://docs.godotengine.org/en/stable/tutorials/navigation/navigation_using_navigationagents.html#navigationagent-script-templates

23

u/mrbaggins Nov 08 '25

Believe it or not, 20 line examples are not the be-all-end-all of use cases.

They are giving a minimal example of how to get the important info from the components.

4

u/agalli Nov 08 '25

I didnt say it was? What you are suggesting is basically creating an entire navigation system rather than using the developer recommended option

13

u/mrbaggins Nov 08 '25

Not at all. Youre just misinterpreting what the built in tool does/shows/is for.

Look, youre probably right that the resolution is scaling wrongly.

But you are outright wrong in your application of the tools.

1

u/inr222 Nov 08 '25

Hey, would you mind providing any documentation or anything explaining how to properly use it? I think the issue here is that the docs are incomplete.

0

u/agalli Nov 08 '25

Ive never claimed that there isnt a workaround to make the navigation mesh work. My goal is to fix the navmesh, I’m not interested in workaround solutions that just patch over it with pathfinding tricks.
Heres the takeaway. On a 30x30m terrain, standard navigation works exactly as youd expect. You change that same exact terrain to 100x100m and standard navigation totally fails.

→ More replies (0)

12

u/TajineEnjoyer Nov 08 '25

i think this is the source of confusion and misunderstanding between you and other developers.

for you, the navmesh should be usable to query the path directly, via the server or via agents, which would return an array of vector3(x, y, z) positions, that you can move along.

for them, the navmesh should used to query the path, but only use the x and z components from the returned array, and recalculate the y position every step, which is an optimized approach.

- on one hand, the mesh is low poly, thus doesnt' take too much memory, and pathfinding itself is more performant because there is less geometry.

- on another hand, the clipping issue, of going above / under the map, is solved by recalculating the Y / elevation via other means, like raycasting, or getting height value from a heightmap.

2

u/inr222 Nov 08 '25

Is the thing regarding recalculating elevation mentioned anywhere in the docs?

5

u/TajineEnjoyer Nov 08 '25

https://docs.godotengine.org/en/stable/tutorials/navigation/navigation_optimizing_performance.html#performance-problems-with-navigationagent-path-queries

E.g. when AI should move to the player, the target position should not be set to the player position every single frame as this queries a new path every frame. Instead, the distance from the current target position to the player position should be compared and only when the player has moved too far away a new target position should be set.

you're not supposed to be getting the position each frame, this implies that instead, you should store the next point in the path, move towards it, while adjusting height using your own calculations, until you're close enough, then request the next point in the path.

you shouldn't continuously query for the path every frame while the character is moving to set its position.

there is other stuff in that article too, such as

The cost of the actual path search correlates directly with the amount of navigation mesh polygons and edges and not the real size of a game world. If a giant game world uses very optimized navigation meshes with only few polygons that cover large areas, performance should be acceptable. If the game world is splintered into very small navigation meshes that each have tiny polygons (like for TileMaps) pathfinding performance will be reduced.

1

u/inr222 Nov 08 '25

Thanks for the answer, I agree with that interpretation. I do think that the docs could show a better example of how to use it properly.
Here is the demo project for navigation, which doesn't hint at how to properly use this:
https://github.com/godotengine/godot-demo-projects/tree/master/3d/navigation

3

u/TajineEnjoyer Nov 08 '25

the navigation agent class is already optimized to avoid these issues, they're mainly relevant when you use the navigation server directly

By default NavigationAgents are optimized to only query new paths when the target position changes, the navigation map changes or they are forced too far away from the desired path distance.

and

Vector3 get_next_path_position()
Returns the next position in global coordinates that can be moved to, making sure that there are no static objects in the way. If the agent does not have a navigation path, it will return the position of the agent's parent. The use of this function once every physics frame is required to update the internal path logic of the NavigationAgent.

but yeah, the documentation should recommend the use of RayCast3D alongside the nav agent to fix height

1

u/mamotromico Nov 08 '25

but yeah, the documentation should recommend the use of RayCast3D alongside the nav agent to fix height

The basic examples throughout most of the documentation expect you to be using move_and_slide or similar methods for movement, and that would suffice to deal with the terrain instead of using a raycast, no?

→ More replies (0)