Description
Tested versions
- Reproducible in:
- Missing APIs in 4.1 and below
System information
Godot v4.3.rc2 - macOS 15.1.0 - Vulkan (Forward+) - integrated Apple M1 Max - Apple M1 Max (10 Threads)
Issue description
Sometimes adding obstructions to a navigation polygon breaks (it disappears) and navigation doesn't work.
My game is randomised so sometimes it works, sometimes not. I believe it's something to do with obstructions sharing a corner with the traversable outline, or that a triangle diagonal is cutting through the obstruction, or both.
This also happens when there are 2 obstructions fully within the traversible outline (no points shared with the outline) but the 2 obstacles share a diagonal corner. I've just reproduced the simplest case as above though.
I would prefer a runtime error than this silently broken behavior. Or perhaps bake returning false in error states instead of void. Or even a validate_points
kind of method. My game is randomly generated so it was really hard to track down why navigation sometimes just didn't work without such feedback.
The navigation documentation mentions for 2D "avoid nesting any outlines inside other outlines of the same type (traversable / obstruction)" but here I've used 1 traversable and 1 obstruction so I don't think that should apply.
Steps to reproduce
- Add a NavigationRegion2D node so you can see debug shapes later.
- Attach script to dynamically generate the navigation polygon.
- Generate outer outline points and inner obstacle points (see repro). In my game I have dynamic tilemap generation and user dynamically places obstacles, but for this repro I've hard coded the points.
- The bug seems to occur when the inner obstacle shares a corner diagonally with the outline, or perhaps when a diagonal of a triangle in the mesh goes through the obstacle (or both).
- Use those outlines to make a navigation polygon. Using just the outline it'll show up (debug enabled), but with the obstacle added the polygon disappears (and navigation doesn't work).
I tried 2 methods of generating the navigation polygon to try to find a workaround but couldn't. Both are in my repro project, the first is commented out. Repeating here inline for easier discussion.
First is just adding the outlines directly (hole is clockwise):
navigation_polygon.add_outline(outer_points)
navigation_polygon.add_outline(hole_points) # this line causes polygon to vanish
bake_navigation_polygon()
Second is going via a mesh with explicit obstacles:
var mesh := NavigationMeshSourceGeometryData2D.new()
mesh.add_traversable_outline(outer_points)
mesh.add_obstruction_outline(hole_points) # this line causes polygon to vanish
NavigationServer2D.bake_from_source_geometry_data(navigation_polygon, mesh)
Neither work as expected. If you comment the indicated line then you can see the outline as expected, it's the hole that is breaking something.
Minimal reproduction project (MRP)
1 file 1 node repro. 2 possible ways to reproduce, 1 is commented out.