如何修改Godot 4.1中NavigationAgent3D的寻路为3D网格型路径
一、核心结论
完全可以修改NavigationAgent3D的寻路逻辑,实现网格型沿指定坐标点移动的需求,主要有两种落地方式:手动指定路径点序列(快速适配需求)、自定义寻路算法(灵活扩展网格逻辑)。
二、方案一:手动指定网格路径点序列(推荐新手优先尝试)
这种方式直接跳过默认A*寻路,让角色沿你预设的网格坐标点依次移动,适配你要的网格型移动效果。
1. 场景适配操作
在你的Player场景中:
- 给
CharacterBody3D添加NavigationAgent3D节点。 - 在Player的脚本中添加可编辑的路径点数组,方便在编辑器中直接填入网格坐标:
extends CharacterBody3D @onready var navigation_agent: NavigationAgent3D = $NavigationAgent3D # 编辑器中可直接添加网格对应的3D坐标点 @export var grid_waypoints: Array[Vector3] = [] var current_point_index: int = 0 # 判定到达路径点的阈值(根据角色大小调整) @export var arrival_threshold: float = 0.5 @export var move_speed: float = 5.0
2. 核心移动逻辑
在脚本的_physics_process中实现路径点遍历与移动:
func _ready(): # 初始化第一个路径点 if grid_waypoints.size() > 0: navigation_agent.set_target_position(grid_waypoints[current_point_index]) func _physics_process(delta): if grid_waypoints.size() == 0: return # 检查是否到达当前路径点 if global_position.distance_to(grid_waypoints[current_point_index]) <= arrival_threshold: current_point_index += 1 # 路径走完后可选择循环或停止 if current_point_index >= grid_waypoints.size(): current_point_index = 0 # 循环路径 # return # 若要停止则取消注释 navigation_agent.set_target_position(grid_waypoints[current_point_index]) # 计算移动方向并执行移动 var next_pos = navigation_agent.get_next_path_position() var move_dir = (next_pos - global_position).normalized() velocity = move_dir * move_speed move_and_slide()
3. 编辑器配置
在Player场景的Inspector面板中,给grid_waypoints数组添加你预设的网格坐标(比如按(0,0,0)、(2,0,0)、(2,0,2)这种固定网格间隔的点),即可让角色沿这些点移动。
三、方案二:自定义3D网格寻路算法(适合复杂网格逻辑)
如果需要动态生成网格路径(而非手动预设),可以跳过NavigationAgent3D的默认寻路,自己实现3D网格版的寻路逻辑,再将计算出的路径点传给角色。
1. 自定义网格寻路示例
先实现一个简单的3D网格路径计算函数(可根据你的网格规则扩展):
# 传入起点、终点、网格单元大小,返回网格路径点序列 func calculate_3d_grid_path(start_pos: Vector3, end_pos: Vector3, grid_size: float) -> Array[Vector3]: var path: Array[Vector3] = [] # 将世界坐标转为网格坐标(取整对齐网格) var start_grid = Vector3(round(start_pos.x/grid_size), start_pos.y, round(start_pos.z/grid_size)) * grid_size var end_grid = Vector3(round(end_pos.x/grid_size), end_pos.y, round(end_pos.z/grid_size)) * grid_size # 示例:生成沿X轴再Z轴的网格路径(实际可替换为自定义A*或其他寻路逻辑) path.append(start_grid) path.append(Vector3(end_grid.x, start_grid.y, start_grid.z)) path.append(end_grid) return path
2. 结合角色移动
在需要触发寻路的时机(比如点击网格)调用该函数,将结果赋值给grid_waypoints数组,再复用方案一中的移动逻辑即可:
# 示例:点击场景触发寻路 func _input(event): if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: var space_state = get_world_3d().direct_space_state var ray_query = PhysicsRayQueryParameters3D.create(get_global_mouse_position(), get_global_mouse_position() - Vector3.UP * 100) var result = space_state.intersect_ray(ray_query) if result: var target_pos = result[0]["position"] # 计算网格路径 grid_waypoints = calculate_3d_grid_path(global_position, target_pos, 2.0) current_point_index = 0 navigation_agent.set_target_position(grid_waypoints[current_point_index])
四、场景适配注意事项
- 若你不需要
NavigationAgent3D的默认导航地图,可以关闭其use_navigation_map属性,完全自定义移动逻辑。 - 开启
NavigationAgent3D的debug_enabled属性,可在编辑器中实时查看路径绘制,方便调试。 - 主场景
TestLevel1中可添加MeshInstance3D绘制网格线,辅助你确定网格坐标点。
内容的提问来源于stack exchange,提问作者Rihards Krastiņš
相关产品推荐
相关产品推荐

