I'd find the closest point (NavigationServer3D.map_get_closest_point()
) and check the distance between them. If it's on the map, the distance would be approximately zero.
Also, that likely gives you a valid spawn position. You could also push in away from original point to spawn away from area edge!
Something like this:
func get_point_on_map(target_point: Vector3, min_dist_from_edge: float) -> Vector3:
var map := get_world_3d().navigation_map
var closest_point := NavigationServer3D.map_get_closest_point(map, target_point)
var delta := closest_point - target_point
var is_on_map = delta.is_zero_approx() # Answer to original question!
if not is_on_map and min_dist_from_edge > 0:
# Wasn't on the map, so push in from edge. If you have thin sections on
# your navmesh, this could push it back off the navmesh!
delta = delta.normalized()
closest_point += delta * min_dist_from_edge
return closest_point
Something similar should also work for 2D.
You could probably also get the nav mesh polygons and do an inside polygon test, but that's probably slower and more hassle.