Creating obstacles through NavigationServer2D does not work
Tested versions
Reproducible 4.3
System information
Godot v4.3.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2070 SUPER (NVIDIA; 31.0.15.5186) - Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz (8 Threads)
Issue description
# for reproduction using drawn line for vertices
extends Line2D
## TileMapLayer for creating obstacle tiles
@export var tilemap_layer:TileMapLayer
## Obstacle's Navigation layer
@export_flags_2d_navigation var obstacle_layer:int
var obstacle_rid:RID
func _ready() -> void:
var _navigation_rid:RID = tilemap_layer.get_navigation_map()
obstacle_rid = NavigationServer2D.obstacle_create()
NavigationServer2D.obstacle_set_map(obstacle_rid, _navigation_rid)
NavigationServer2D.obstacle_set_avoidance_layers(obstacle_rid, obstacle_layer)
NavigationServer2D.obstacle_set_position(obstacle_rid, global_position)
# use drawn points for vertices (Counter-clock for repel as documented)
NavigationServer2D.obstacle_set_vertices(obstacle_rid, points)
NavigationServer2D.obstacle_set_avoidance_enabled(obstacle_rid, true)
NavigationServer2D.obstacle_set_paused(obstacle_rid, false)
NavigationServer2D.map_force_update(_navigation_rid)
func _exit_tree() -> void:
NavigationServer2D.free_rid(obstacle_rid)
NavigationServer2D returns that it has registered obstacle RID, but debug drawing doesn't look like something was changed. NavigationAgent2D still gives a path through the obstacle place with enabled avoidance.
Steps to reproduce
- create an obstacle with GDscript calling NavigationServer2D
- use counter-clock vertices
- set common avoidance_layer flags
- enable avoidance on NavigationAgent2D
- walk through zone that's supposed to be navigation obstacle
Minimal reproduction project (MRP)
NavigationServer2D returns that it has registered obstacle RID, but debug drawing doesn't look like something was changed.
Debug is drawn by nodes. If you dont use nodes but the server directly you have no debug visuals and need to draw your own debug.
NavigationAgent2D still gives a path through the obstacle place with enabled avoidance.
Avoidance and pathfinding are different systems. RVO Avoidance works with velocities, it has nothing to do with the navigation mesh surface based pathfinding.
The obstacle that was created here would affect the avoidance velocity, it will do nothing for pathfinding. The only thing that affects pathfinding is the navigation mesh surface. The obstacle shape can be baked to the navigation mesh surface when affect_navigation_mesh=true is enabled but it still needs to be baked with the navigation mesh like any other object that should affect the pathfinding.
That sounds wrong.
- Documentation says
Creates a new navigation obstacle.- Nothing about avoidance or pathfinding or only for affecting velocity.
- How velocity can help if the path goes through the obstacle?
If NavigationServer doesn't create an actual obstacle than what does?
This also not work on Linux 4.3 Stable.
If use NavigationServer2D.obstacle_set_map
E.g.:
new_obstacle_rid= NavigationServer2D.obstacle_create()
NavigationServer2D.obstacle_set_position(new_obstacle_rid, Vector2(20, 20))
NavigationServer2D.obstacle_set_radius(new_obstacle_rid, 0.0)
var outline = PackedVector2Array([Vector2(-100, -100), Vector2(150, -100), Vector2(100, 100), Vector2(-100, 100)])
NavigationServer2D.obstacle_set_vertices(new_obstacle_rid, outline)
NavigationServer2D.obstacle_set_avoidance_enabled(new_obstacle_rid, true)
NavigationServer2D.obstacle_set_map(new_obstacle_rid, map_id)
The return of 'NavigationServer2D.map_get_obstacles' will contains this obstacle id,
but it does not work with PATH FINDING.
Instead.
If I use 'add_obstruction_outline' of the same points to the source_geometry and it would work
E.g.:
var outline = PackedVector2Array([Vector2(-100, -100), Vector2(150, -100), Vector2(100, 100), Vector2(-100, 100)])
source_geometry.add_obstruction_outline(outline)
NavigationServer2D.bake_from_source_geometry_data_async(nav_polygon, source_geometry, callback_baking)
Also, Using the obstacle Node NavigationObstacle2D with NavigationRegion2D works.
A further investigation found that:
-
create obs0 and then create obs1, obs0 not valid , which obs0 should be valid
-
remove obs1, the obs0 became valid
-
remove obs0, the obs0 remains valid, which obs0 should be invalid
create / remove obs1 just use bake_from_source_geometry_data_async, but call this when creating obs0 seems takes no effect
Closing as this was already explained in my original answer.
How obstacles and navmesh work is documented at length in the official documentation in multiple places. There are 2 dedicated pages for navmesh and obstacles alone that can be found here https://docs.godotengine.org/en/latest/tutorials/navigation/navigation_using_navigationmeshes.html and here https://docs.godotengine.org/en/latest/tutorials/navigation/navigation_using_navigationobstacles.html explaining it further. If you use the server api instead of nodes you also need to bake your obstacles this way to the navmesh. The documentation has examples for this.