You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot Navigation2D get_simple_path返回空路径数组问题排查

问题根本原因

返回空路径是两个核心逻辑错误导致的,和坐标转换、optimize开关无关:

  • 动态创建的Navigation2D节点未加入场景树。Godot导航系统只会同步已进入场景树的Navigation2D节点下的导航网格数据,你通过.new()实例化节点后从未调用add_child()挂载到场景,节点本身收集不到任何导航多边形信息,调用路径查询接口必然返回空数组。
  • 导航多边形挂载逻辑完全错误:
    • 你把所有瓦片的导航多边形都赋值给同一个预创建的$NavigationPolygonInstance节点,后写入的多边形会直接覆盖之前的内容,最终仅单个瓦片的导航区域生效,整个导航面完全不连通。
    • 你尝试为每个瓦片创建独立的NavigationPolygonInstance实例,但既没有将实例挂载到Navigation2D节点下,也没有设置对应瓦片的坐标偏移,这类游离节点不会被导航系统识别注册。
    • 你生成多边形轮廓时使用的是全局瓦片坐标,而NavigationPolygon的轮廓坐标是相对于自身节点的局部坐标,就算挂载成功也会出现所有导航多边形堆叠在原点的问题。
修复方案

按以下步骤修改即可:

  1. 初始化Navigation2D节点并挂载到场景树
    不要在路径查询的循环里重复创建Navigation2D,把节点初始化逻辑放到TileMap生成的初始化阶段,保证Navigation2D和TileMap为同级节点(坐标系一致,减少多余坐标转换):
# 放在TileMap、导航网格生成逻辑的最前面,不要放到路径查询循环中
var navigation = Navigation2D.new()
add_child(navigation) # 挂载到当前节点,和TileMap保持同级即可
  1. 为每个可行走瓦片创建独立的导航多边形实例
    遍历可行走瓦片生成导航区域时,每个瓦片单独创建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)
  1. 简化路径查询逻辑
    只要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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 21:09:21