Godot Navigation2D get_simple_path返回空路径数组问题排查
问题根本原因
返回空路径是两个核心逻辑错误导致的,和坐标转换、optimize开关无关:
- 动态创建的
Navigation2D节点未加入场景树。Godot导航系统只会同步已进入场景树的Navigation2D节点下的导航网格数据,你通过.new()实例化节点后从未调用add_child()挂载到场景,节点本身收集不到任何导航多边形信息,调用路径查询接口必然返回空数组。 - 导航多边形挂载逻辑完全错误:
- 你把所有瓦片的导航多边形都赋值给同一个预创建的
$NavigationPolygonInstance节点,后写入的多边形会直接覆盖之前的内容,最终仅单个瓦片的导航区域生效,整个导航面完全不连通。 - 你尝试为每个瓦片创建独立的
NavigationPolygonInstance实例,但既没有将实例挂载到Navigation2D节点下,也没有设置对应瓦片的坐标偏移,这类游离节点不会被导航系统识别注册。 - 你生成多边形轮廓时使用的是全局瓦片坐标,而NavigationPolygon的轮廓坐标是相对于自身节点的局部坐标,就算挂载成功也会出现所有导航多边形堆叠在原点的问题。
- 你把所有瓦片的导航多边形都赋值给同一个预创建的
修复方案
按以下步骤修改即可:
- 初始化Navigation2D节点并挂载到场景树
不要在路径查询的循环里重复创建Navigation2D,把节点初始化逻辑放到TileMap生成的初始化阶段,保证Navigation2D和TileMap为同级节点(坐标系一致,减少多余坐标转换):
# 放在TileMap、导航网格生成逻辑的最前面,不要放到路径查询循环中 var navigation = Navigation2D.new() add_child(navigation) # 挂载到当前节点,和TileMap保持同级即可
- 为每个可行走瓦片创建独立的导航多边形实例
遍历可行走瓦片生成导航区域时,每个瓦片单独创建NavigationPolygonInstance,设置正确坐标后挂载到Navigation2D节点下,禁止共用同一个实例:
# 替换成你项目实际的瓦片尺寸 const TILE_SIZE = 32 # 遍历所有可行走瓦片坐标(x,y)时执行以下逻辑 var polygon = NavigationPolygon.new() # 多边形轮廓使用相对于NavigationPolygonInstance的局部坐标,单瓦片轮廓直接从(0,0)开始绘制 var outline = PoolVector2Array([ Vector2(0, 0), Vector2(0, TILE_SIZE), Vector2(TILE_SIZE, TILE_SIZE), Vector2(TILE_SIZE, 0) ]) polygon.add_outline(outline) polygon.make_polygons_from_outlines() # 每个瓦片创建独立的导航实例 var nav_instance = NavigationPolygonInstance.new() nav_instance.navpoly = polygon # 设置实例位置为对应瓦片的世界坐标,和TileMap瓦片位置对齐 nav_instance.position = Vector2(x * TILE_SIZE, y * TILE_SIZE) # 挂载到Navigation2D节点下,才会被导航系统注册 navigation.add_child(nav_instance)
- 简化路径查询逻辑
只要Navigation2D和TileMap坐标系一致,直接用TileMap自带的坐标转换接口即可,不需要多余的to_local/to_global转换,同时优化起止点随机逻辑,避免漏处理:
var door_total = all_door_coords.size() for start_loc in all_door_coords: var start_pos = tilemap.map_to_world(start_loc) # 循环随机直到选到不重复的终点,避免用continue跳过导致逻辑遗漏 var end_loc = all_door_coords[randi() % door_total] while end_loc == start_loc: end_loc = all_door_coords[randi() % door_total] var end_pos = tilemap.map_to_world(end_loc) var path = navigation.get_simple_path(start_pos, end_pos, true) # 加个空路径判断方便调试连通性问题 if path.size() == 0: print("起点%s 到终点%s 无连通路径" % [start_loc, end_loc]) continue for pos in path: var map_pos = tilemap.world_to_map(pos) tilemap.set_cellv(map_pos, -1)
额外注意事项
- Godot 3.x版本下请确认Navigation2D和所有NavigationPolygonInstance的
navigation_layers属性一致,层级不匹配也会导致查询返回空路径。 - 导航网格挂载完成后需要一帧时间同步到导航系统,如果生成完导航立刻查询路径,可以先调用
navigation._update_navigation()强制刷新导航数据(仅调试阶段使用,正式逻辑建议等一帧后再执行路径查询)。
内容的提问来源于stack exchange,提问作者DotFX
相关产品推荐
相关产品推荐

