NavigationServer2D.map_get_closest_point issue

Godot Version

4.6 Stable Windows

Question

Hello

I have a problem with the NavigationServer2D.map_get_closest_point I use to create enemies spawn points.

When player change room, the new one is instantiated, the player is moved from the old one to the new one and then the old one is queue free. When the new room is added, it’s navigation polygon is created. When everything is done a signal is triggered to start the wave cycle. A 3s Timer is started and when it timeout spawn points are added.

To define spawn points, this is my code :

func _define_possible_spawn_points()->Array[Vector2]:
#### get nav polygon and find x and y max et min and get a rect who covers the entire area
var nav_polygon = $GroundedNavigationRegion.navigation_polygon.get_vertices()
print("NAV_PLOY = ",nav_polygon)
var min_rect:=Vector2(10000,10000)
var max_rect:=Vector2(-10000,-10000)
for point in nav_polygon:
	if point.x < min_rect.x :
		min_rect.x = point.x
	if point.x > max_rect.x :
		max_rect.x = point.x	
	if point.y < min_rect.y :
		min_rect.y = point.y
	if point.y > max_rect.y :
		max_rect.y = point.y
print("max_rect = ",max_rect, " min_rect = ",min_rect)
#### slice the rect into small rectangles and check if central point of it is on the nav_region. if yes, add to possibles_spawn_points
## define size of spawn point and check how many can be put on x and y. the rest is removed from min/max rect in order to center
var possible_spawn_points:Array[Vector2]
var spawn_space_rect:=Vector2(22,16)
var nb_x = floor((max_rect.x-min_rect.x)/spawn_space_rect.x)
var px_restants_x = (max_rect.x-min_rect.x)-(nb_x*spawn_space_rect.x)
var nb_y = floor((max_rect.y-min_rect.y)/spawn_space_rect.y)
var px_restants_y = (max_rect.y-min_rect.y)-(nb_y*spawn_space_rect.y)
min_rect.x+=(px_restants_x/2)
min_rect.y+=(px_restants_y/2)
max_rect.x-=(px_restants_x/2)
max_rect.y-=(px_restants_y/2)

var map := get_world_2d().navigation_map
print("map = ",map)
## 2 find center and check if it's on nav-area
for row in nb_y:
	for col in nb_x:
		var coord_to_check:=Vector2(min_rect.x+(col*spawn_space_rect.x)+spawn_space_rect.x/2,min_rect.y+(row*spawn_space_rect.y)+spawn_space_rect.y/2)
		var closest_point := NavigationServer2D.map_get_closest_point(map, coord_to_check)
		var delta := closest_point - coord_to_check
		var is_on_map = true if delta.length() < 0.01 else false 
		print("to_check = ",coord_to_check," closest = ",closest_point, " > in on map = ",is_on_map)
		if is_on_map:
			possible_spawn_points.append(coord_to_check)
return possible_spawn_points

Then I instanciate a number of spawn points randomly according to number of enemies to add in the room. Positions of spawn points are taken from the possible_spaw_points array.

I used this code for month without any problem. About 15 people playtested it on their own machine without problem either.
Today I upgraded Godot from 4.4 to 4.6, and now sometimes the possible_spawn_points is returned empty. It appends about 1 time on 20 and can’t figure out why. I assume it’s a problem with the NavigationServer2D.map_get_closest_point because the prints show this when issue appends :

NAV_PLOY = [(564.0, 315.0), (76.0, 315.0), (76.0, 85.0), (564.0, 85.0)]
max_rect = (564.0, 315.0) min_rect = (76.0, 85.0)
map = RID(13370233192448)
to_check = (89.0, 96.0) closest = (0.0, 0.0) > in on map = false
to_check = (111.0, 96.0) closest = (0.0, 0.0) > in on map = false
to_check = (133.0, 96.0) closest = (0.0, 0.0) > in on map = false
to_check = (155.0, 96.0) closest = (0.0, 0.0) > in on map = false
... etc for every point(about 300 depending of the room)

and when it’s working as intended :

NAV_PLOY = [(485.0, 293.0), (564.0, 315.0), (76.0, 315.0), (443.0, 293.0), (197.0, 293.0), (155.0, 293.0), (485.0, 181.0), (485.0, 107.0), (564.0, 85.0), (76.0, 85.0), (443.0, 107.0), (155.0, 219.0), (443.0, 219.0), (197.0, 219.0), (197.0, 181.0), (443.0, 181.0), (197.0, 107.0), (155.0, 107.0), (485.0, 219.0), (155.0, 181.0)]
max_rect = (564.0, 315.0) min_rect = (76.0, 85.0)
map = RID(13370233192448)
to_check = (89.0, 96.0) closest = (89.0, 96.0) > in on map = true
to_check = (111.0, 96.0) closest = (111.0, 96.0) > in on map = true
to_check = (133.0, 96.0) closest = (133.0, 96.0) > in on map = true
to_check = (155.0, 96.0) closest = (155.0, 96.0) > in on map = true
to_check = (177.0, 96.0) closest = (177.0, 96.0) > in on map = true
(...)
to_check = (177.0, 112.0) closest = (177.0, 107.0) > in on map = false
to_check = (199.0, 112.0) closest = (199.0, 112.0) > in on map = true

I checked the nav polygon is always correctly set and with debog navigation visible correctly appears. When issue appends, the previous room isn’t anymore in the tree according to the distant tree inspector

Note : The second Console output correspond to the screenshot

If anyone have an idea what’s happening and/or someting to prevent it I’d appreciate the help

Thanks !

Update :

It seems related to : `NavigationServer.map_changed` doesn't result in usable map on first iteration. · Issue #112652 · godotengine/godot · GitHub and Speed up NavigationServer3D synchronizations by smix8 · Pull Request #112908 · godotengine/godot · GitHub

Indeed, the map_changed signal is triggered between 2 and 3 times (while it’s updated only once) and only the last time I can get a closes points different of (0.0,0.0). The problem seems to come from the delay to sync the NavigationServer (2D in my case)

I tried several things. Among them I wait for the signal map_changed and immediately check for a close point from the center of the screen. If it returns something else than (0.0,0.0), I trigger a signal to continue. This signal is always and only triggered when the la signal map_changed is. I also added a timer in case the test is never true to trigger continue signal with a fallback solution. With a timer of 2s, about 1 on 2 times continue is triggered with the timeout. With 3s it’s more 1 / 20.
As in the initial code the tempo before creating spawn points was 3s, it makes sense.
With 10s tempo, it never fails, so it’s a problem with the very very long delay to update NavigationServer I guess. I don’t know how to fix this as far as there is no method to force update.

I’ll try on a very less powerfull PC to see if delays are longer, witch could be a big problem.