
文档教程游戏开发【免费下载链接】godot-docsGodot Engine official documentation项目地址https://gitcode.com/GitHub_Trending/go/godot-docs点击查看免费下载本篇以 Godot 官方文档仓库中的 NavigationAgent3D 类参考 为核心骨架系统讲解 3D 导航代理的寻路Pathfinding、路径跟随Path Following与基于 RVO 的动态避障Avoidance三大能力并逐一拆解其全部属性、信号与方法。读完本文你将能够基于 NavigationAgent3D 为 Node3D / CharacterBody3D / RigidBody3D 父节点搭建一套可复用的寻路移动框架理解每一个配置项对路径质量与避障效果的影响并能结合 NavigationServer3D 底层 API 与 NavigationObstacle 进行深度定制。NavigationAgent3D 是什么NavigationAgent3D继承自Node Object是 Godot 导航系统中面向 3D 场景的一站式辅助节点。它的核心职责是为挂载它的父节点在 3D 空间中寻路到目标位置并在移动过程中避开静态与动态障碍物。其 2D 对应版本是NavigationAgent2D两者 API 结构几乎一致只是坐标维度不同。它的核心设计要点包括计算结果交由父节点执行NavigationAgent3D 本身不移动任何节点路径点与世界坐标计算结果返回给父节点后由你自己的移动代码驱动实际运动参见配套教程 navigation_using_navigationagents.rst。动态障碍采用 RVOReciprocal Velocity Obstacles相互速度障碍避障避障计算发生在物理步骤physics step之前因此寻路信息可以在物理帧内安全使用。依赖导航数据代理本身不产生导航网格必须存在有效的导航地图NavigationMap与导航网格NavigationMesh一般由 NavigationRegion3D 提供或烘焙生成路径查询才有意义。标注为 Experimental类参考文档顶部明确注明 Experimental意味着该类的 API 在未来版本中可能被修改或移除生产项目应留意版本升级。注意设置target_position之后必须在每个物理帧调用一次get_next_path_position()来更新代理内部路径逻辑该方法返回的向量位置应作为父节点下一步的移动目标位置。属性全景一张表看懂 32 个配置项NavigationAgent3D 的全部属性、类型与默认值如下表所示默认值来自 class_navigationagent3d.rst属性类型默认值用途归类avoidance_enabledboolfalse是否启用 RVO 避障回调avoidance_layersint位掩码1本代理所在的避障层avoidance_maskint位掩码1本代理需要避开的避障层avoidance_priorityfloat1.0避障优先级debug_enabledboolfalse是否显示调试可视化debug_path_custom_colorColorColor(1, 1, 1, 1)自定义路径调试颜色debug_path_custom_point_sizefloat4.0自定义路径点渲染尺寸debug_use_customboolfalse是否使用自定义调试颜色heightfloat1.02D 避障模式下代理的垂直高度keep_y_velocitybooltrue2D 避障后是否保留 y 轴速度max_neighborsint10避障计算考虑的最大邻居数max_speedfloat10.0避障允许的最大速度navigation_layersint位掩码1寻路可用的导航层neighbor_distancefloat50.0搜索其他代理的距离path_desired_distancefloat1.0判定到达路径点的阈值path_height_offsetfloat0.0路径位置 y 轴偏移path_max_distancefloat5.0允许偏离理想路径的最大距离path_metadata_flags位掩码7路径附带元数据开关path_postprocessing枚举0路径后处理模式path_return_max_lengthfloat0.0返回路径最大长度0不限path_return_max_radiusfloat0.0返回路径最大半径0不限path_search_max_distancefloat0.0寻路搜索最大距离0不限path_search_max_polygonsint4096寻路搜索最大多边形数0不限pathfinding_algorithm枚举0寻路算法radiusfloat0.5避障代理的身体半径simplify_epsilonfloat0.0路径简化量世界单位simplify_pathboolfalse是否返回简化路径target_desired_distancefloat1.0判定到达目标的阈值target_positionVector3Vector3(0, 0, 0)寻路目标位置time_horizon_agentsfloat1.0针对其他代理的避障预测时间time_horizon_obstaclesfloat0.0针对静态障碍的避障预测时间use_3d_avoidanceboolfalse使用 3Dxyz还是 2Dxz避障velocityVector3Vector3(0, 0, 0)期望速度交由避障模拟修正这些属性可以按功能分成三大组寻路配置、路径跟随配置、避障配置下文逐一详解。寻路配置控制路径如何被算出来当设置target_position全局坐标后代理会向NavigationServer3D请求一条从当前位置到目标位置的新路径。路径的质量与形态由以下属性共同决定。navigation_layers限定可用的导航网格navigation_layers是一个位掩码bitfield决定代理在寻路时可以使用哪些导航层的导航区域NavigationRegion。默认值为1仅第 1 层。运行时修改该值会清空当前导航路径并依据新图层重新生成路径。配套方法get_navigation_layer_value(layer_number)与set_navigation_layer_value(layer_number, value)允许以 132 的数字逐位读取或开关图层。这是实现不同角色走不同区域的关键手段——例如普通地面单位只走地面层、飞行单位额外走空中层具体用法可参考教程 navigation_using_navigationlayers.rst。pathfinding_algorithm选择寻路算法该属性决定路径查询使用哪种寻路算法。当前枚举定义于 class_navigationpathqueryparameters3d.rst只有一个成员PATHFINDING_ALGORITHM_ASTAR 0使用默认的 A* 寻路算法。默认值即此。path_postprocessing路径后处理寻路算法找到的是穿过导航网格多边形的原始路径走廊raw path corridor后处理决定其如何被整形为最终返回的路径点序列PATH_POSTPROCESSING_CORRIDORFUNNEL 0默认对原始路径走廊应用漏斗算法funnel algorithm得到走廊内最短路径。该模式非常依赖导航网格的多边形布局在基于格子/瓦片的布局中锯齿状的走廊可能产生对角线移动的人工拐角。PATH_POSTPROCESSING_EDGECENTERED 1把每个路径点居中到所经过导航网格多边形边的中点。对限制单位在格子中心移动的瓦片/网格布局更友好。PATH_POSTPROCESSING_NONE 2不做后处理直接返回原始路径走廊。path_metadata_flags路径元数据开关这是一个位掩码决定路径点附带多少额外信息这些信息会随waypoint_reached/link_reached信号的 details 字典传出PATH_METADATA_INCLUDE_NONE 0不包含任何元数据。PATH_METADATA_INCLUDE_TYPES 1包含每个路径点经过的导航图元类型region 区域 或 link 链接。PATH_METADATA_INCLUDE_RIDS 2包含路径点经过的 region/link 的RID。PATH_METADATA_INCLUDE_OWNERS 4包含管理这些 region/link 的Object的ObjectID。PATH_METADATA_INCLUDE_ALL 7包含全部元数据。属性默认值正是7。警告来自配套教程关闭路径元数据标志会连带禁用代理上相关的信号发射。例如不包含 types 元数据时waypoint_reached的 details 中就缺少 type 字段。simplify_path 与 simplify_epsilon路径简化simplify_path true时返回的路径会移除不重要的路径点得到一个简化版本。simplify_epsilon控制简化量世界单位。其内部使用Ramer-Douglas-Peucker 算法的变体进行曲线点抽稀decimation。路径简化对两类场景特别有价值转向/steering类代理以及在开阔场地中启用避障的代理——它可以缓解因路径点过密而导致的抖动与来回摆动问题。path_search_max_distance 与 path_search_max_polygons搜索预算上限这两个属性用于限制寻路在目标不可达或极远时的搜索开销path_search_max_distance默认0.0搜索的多边形距离起点多边形超过该值世界单位时寻路中止转而返回起点到当前已找到的最近目标多边形的路径。path_search_max_polygons默认4096搜索的多边形数量达到该上限时中止行为同上。两者取值0或负数均视为不限此时寻路会搜索所有与起点连通的导航多边形直到找到目标或穷尽所有选项。在大型关卡中合理设置这两个值可以避免寻路查询吃掉过多的单帧开销更多性能建议参见 navigation_optimizing_performance.rst。path_return_max_length 与 path_return_max_radius返回路径裁剪path_return_max_length默认0.0返回路径的最大长度世界单位超过即被裁剪。path_return_max_radius默认0.0返回路径距路径起点即第一个路径位置的最大半径世界单位超出即裁剪。与长度限制相比它允许代理在需要绕过一个拐角时多走出一段距离。注意半径裁剪是以第一个路径位置为球心、仅针对导航网格上的实际路径点进行的球面裁剪。路径跟随每物理帧驱动内部路径逻辑寻路只是第一步真正的走起来依赖路径跟随。NavigationAgent3D 拥有独立的内部路径推进逻辑驱动它的唯一入口就是get_next_path_position()。标准调用模式func _physics_process(delta: float) - void: # 地图尚未同步过一次时不要查询避免返回空路径 if NavigationServer3D.map_get_iteration_id(navigation_agent.get_navigation_map()) 0: return # 路径已完成时尽早返回避免原地抖动 if navigation_agent.is_navigation_finished(): return var next_path_position: Vector3 navigation_agent.get_next_path_position() # 用自己的移动代码朝 next_path_position 移动父节点关键要点来自 navigation_using_navigationagents.rst必须每物理帧调用一次get_next_path_position()直到is_navigation_finished()返回true。到达目标或路径终点后不要再调用该函数否则反复的路径更新会让站定的代理原地抖动。代理没有有效路径时get_next_path_position()返回的是父节点当前位置。导航系统永远不会替你移动父节点移动完全由你的脚本负责。代理也可以在_process中使用但内部更新仍受限于每物理帧一次的节奏。三个距离阈值决定何时推进路径跟随的行为由三个距离属性协同控制path_desired_distance默认1.0代理距下一个路径点小于该值时内部路径索引推进到下一个路径点。设太高会跳过路径点可能冲出导航网格设太低会因每帧都过冲而陷入不断重算路径的循环。target_desired_distance默认1.0代理距目标小于该值时认为目标已到达、路径结束触发target_reached信号并结束导航。设置大于path_desired_distance导航会在到达最后一个路径点之前提前结束。设置小于path_desired_distance导航不会在到达最后路径点后立刻结束可以更贴近目标但设得过低同样会陷入重算循环。path_max_distance默认5.0代理因避障等原因偏离理想路径超过该距离时触发重新规划理想路径并发射path_changed信号。path_height_offsety 轴视觉偏移path_height_offset默认0.0会从该代理的每个路径位置的 y 轴值中减去该偏移量。它只影响路径位置的读取层不会改变或影响导航网格本身与寻路查询结果。官方文档明确指出若要支持不同体型的代理正确做法是为不同体型以不同的NavigationMesh.agent_radius烘焙导航网格并使用不同的导航地图而不是靠 height offset 凑合。get_current_navigation_path 与 get_current_navigation_path_indexget_current_navigation_path()返回从起点到终点的全局坐标路径点数组PackedVector3Array。它只在目标变化或需要重算时更新不应用于直接移动——直接修改数组会破坏代理内部路径逻辑应当始终通过get_next_path_position()驱动移动。get_current_navigation_path_index()返回代理当前处在路径数组的哪个索引。get_path_length()返回当前路径总长若路径仍在计算或尚未请求返回0.0。路径跟随常见问题官方文档原版要点返回空路径在导航地图同步之前例如_ready()中查询路径可能得到空结果此时get_next_path_position()返回父节点位置代理会认为路径已结束。解决延迟调用或通过地图变更信号等回调等待同步完成。代理在两位置间跳舞通常由每帧频繁重算路径引起如path_max_distance设得过短。寻路要找导航网格上最近的有效点若每帧都重算第一个路径点会在代理前后不断切换。偶尔回溯代理移动太快一帧内越过path_desired_distance判定而索引未推进导致回头走向身后的路径点。加大 desired 距离、降低速度或改善导航网格布局避免小区域内边过密通常可修复。偶尔向后看一帧与跳舞同因加上代理正好站在网格边/边连接处时路径点可能因精度问题略偏后方对即时转向朝向路径点的代理可见。RVO 避障让多个代理互相让路避障是 NavigationAgent3D 相对普通纯寻路方案的核心增量。其底层是RVO相互速度障碍模拟避障代理在抽象空间中只是平面上的圆2D 避障或空三维空间中的球3D 避障没有导航网格或物理碰撞的任何信息相关说明见 navigation_using_navigationagents.rst。避障工作流三步开启avoidance_enabled true代理注册到 NavigationServer3D 的 RVO 避障回调中。注意大量代理同时开启避障有显著性能开销只对当前确实需要避障的代理开启。属性面板对应下图中的勾选项连接velocity_computed信号接收避障计算出的安全速度每物理帧把父节点的当前速度写入velocity属性并改用信号回调中的safe_velocity驱动移动func _physics_process(delta: float) - void: ... var next_path_position: Vector3 navigation_agent.get_next_path_position() var new_velocity: Vector3 global_position.direction_to(next_path_position) * movement_speed if navigation_agent.avoidance_enabled: navigation_agent.set_velocity(new_velocity) else: _on_velocity_computed(new_velocity) func _on_velocity_computed(safe_velocity: Vector3) - void: velocity safe_velocity move_and_slide()注意两点官方文档明确强调只有同一地图上同样注册了避障的其他代理才会被纳入避障计算。即使只用避障也必须设置target_position否则velocity_computed收到的safe_velocity永远是零向量。避障在_physics_process()中设置 velocity、以velocity_computed信号回调safe_velocity的流程如下图中为代理启用避障与信号连接的示意图避障相关属性逐一解读radius默认0.5避障代理的身体半径——是身体本身不是避障机动开始的距离那是neighbor_distance的事。注意它不影响普通寻路要改变角色寻路半径应使用不同NavigationMesh.agent_radius烘焙网格 不同导航地图。height默认1.0仅 3D 有2D 避障模式下代理的垂直高度。代理会忽略当前位置height之上/之下的其他代理或障碍。3D 避障不使用 height只靠半径球。neighbor_distance默认50.0搜索其他代理的距离。调低可减少计算开销。max_neighbors默认10半径重叠时最多考虑多少个邻居。调低可省性能但过低会导致代理无视避障。time_horizon_agents默认1.0对其他代理的速度安全预测时间秒。越大代理越早对其他代理作出反应但速度选择自由度越小过大会显著拖慢移动。必须为正数。time_horizon_obstacles默认0.0对静态避障障碍的速度安全预测时间秒。同样越大越早反应、越小越灵活过大拖慢移动必须为正数。max_speed默认10.0避障计算允许的最大速度。若父节点实际移动快于该值safe_velocity可能不够准确而无法有效避撞。use_3d_avoidance默认falsetrue在 3D 中全方位xyz计算避障速度适合空中、水下或太空玩法。3D 避障代理只避开同样使用 3D 避障的代理只对基于半径的障碍作出反应忽略基于顶点的静态障碍。false沿 x、z 轴忽略 y 轴做 2D 避障。2D 代理只避开 2D 代理可对半径障碍与顶点障碍都作出反应位于其当前位置height上下的其他 2D 代理会被忽略。注意2D 与 3D 避障运行在两套独立的避障模拟中分属两边的代理互相不影响。avoidance_layers默认1与avoidance_mask默认1类似物理层Physics Layers的位掩码。代理只避开自己的 mask 某一位 与对方 avoidance_layers 某一位匹配的避障对象。配套方法get/set_avoidance_layer_value、get/set_avoidance_mask_value支持按 132 逐位操作。avoidance_priority默认1.0高优先级代理不为低优先级代理调整速度而低优先级代理需要更多调整来躲避高优先级代理。可用于让重要 NPC 在避障模拟中优先通行而不必频繁改动整个图层/掩码。keep_y_velocity默认true使用 2D 避障时记录设定的 y 轴速度并在避障步骤后重新应用。2D 避障本身在平坦平面上模拟、没有 y 轴此选项可缓和起伏 3D 几何体上最明显的穿模。velocity默认Vector3(0, 0, 0)设置新的期望速度避障模拟会尽量满足它但会为避开其他代理与障碍而修正。代理被传送teleport到新位置时应同时调用set_velocity_forced()重置内部模拟速度否则旧速度残留可能让代理瞬间冲出去。通过 NavigationServer3D 直接控制避障官方教程也给出了不依赖节点属性、直接调用 NavigationServer3D API 的方式navigation_using_navigationagents.rst对应类参考 class_navigationserver3d.rst 中的agent_set_avoidance_enabled、agent_set_avoidance_callback、agent_set_use_3d_avoidance、agent_set_velocity_forced等extends NavigationAgent3D func _ready() - void: var agent: RID get_rid() # 启用避障 NavigationServer3D.agent_set_avoidance_enabled(agent, true) # 创建避障回调 NavigationServer3D.agent_set_avoidance_callback(agent, Callable(self, _avoidance_done)) # 切换到 3D 避障 NavigationServer3D.agent_set_use_3d_avoidance(agent, true) # 关闭避障 NavigationServer3D.agent_set_avoidance_enabled(agent, false) # 删除避障回调传入空 Callable NavigationServer3D.agent_set_avoidance_callback(agent, Callable()) # 切回 2D 避障 NavigationServer3D.agent_set_use_3d_avoidance(agent, false)注意agent_set_avoidance_callback创建的回调独立于 SceneTree 状态被处理只要代理在导航地图上且未被释放就会派发用空Callable再次调用即可停用派发。set_velocity_forced()以指定速度替换避障模拟中的内部速度传送后应在同一帧调用频繁调用会让代理卡住。配合 NavigationObstacle 使用避障空间本身没有环境信息NavigationObstacle3D可以补上环境约束详见 navigation_using_navigationobstacles.rst静态障碍填充vertices顶点轮廓多边形即视为静态是避障代理不可穿越的硬边界类似物理碰撞但只作用于避障。静态障碍仅对 2D 避障代理生效。动态障碍radius 0即为动态作为请离我远一点的软性对象像避让其他代理一样避让。2D 用圆、3D 避障用球定义边界。障碍同样使用avoidance_layers位掩码所有自己 avoidance_mask 中某一位与该层匹配的代理都会避让该障碍。信号与代理状态交互NavigationAgent3D 共定义 6 个信号是驱动游戏逻辑动画、战斗、对话触发的主要接口信号参数触发时机link_reached(details)Dictionary代理进入下一个路径位置且该位置是**导航链接NavigationLink3D**时距离小于path_desired_distancewaypoint_reached(details)Dictionary代理进入下一个路径位置距离小于path_desired_distance时target_reached()无代理进入目标target_desired_distance范围内时每条已加载路径只发射一次且在navigation_finished之前navigation_finished()无导航结束可达则到达目标、不可达则走完最后路径点每条已加载路径只发射一次且在target_reached之后path_changed()无路径被更新之前为空、导航地图变更、或代理偏离超过path_max_distancevelocity_computed(safe_velocity)Vector3避障速度计算完成时只要avoidance_enabled true且代理有导航地图每次更新都会发射details 字典的元数据字段waypoint_reached(details)依据path_metadata_flags可能包含position到达路径点位置、type该路径点所在导航图元类型region 或 link、rid所在 region/link 的 RID、owner管理该图元的对象。link_reached(details)在waypoint_reached基础上因type恒为PATH_SEGMENT_TYPE_LINK即 NavigationPathQueryResult3D 中PATH_SEGMENT_TYPE_LINK 1还可能包含link_entry_position若 owner 是NavigationLink3D为代理进入的链接端点全局位置link_exit_position若 owner 是NavigationLink3D为代理离开的链接端点全局位置。递归警告类参考原文get_next_path_position()等若干方法可能触发新的路径计算。若在代理信号的回调如waypoint_reached里调用这些方法可能造成无限递归。官方建议在物理步骤中调用这些方法或使用Object.call_deferred()/Object.CONNECT_DEFERRED延迟到帧末执行。方法与状态查询完整 API 速查除get_next_path_position()外常用方法如下完整签名见 class_navigationagent3d.rst方法返回说明distance_to_target()float基于代理全局位置到目标的距离需先设target_position才准确get_current_navigation_path()PackedVector3Array当前完整路径全局坐标仅供读取get_current_navigation_path_index()int当前路径索引get_current_navigation_result()NavigationPathQueryResult3D当前路径的完整查询结果get_final_position()Vector3当前路径可达的最终位置全局坐标路径更新path_changed时可能变化get_navigation_map()RID返回节点上设置的导航地图 RID若直接用 NavigationServer API 改了代理的地图节点不会感知应用set_navigation_map()get_path_length()float当前路径总长仍在计算或未请求时为0.0get_rid()RID本代理在 NavigationServer3D 上的 RIDis_navigation_finished()bool导航是否结束可达则到目标、不可达则到最后一个路径点。true后应停止调用get_next_path_position()等更新函数避免站立抖动is_target_reachable()boolget_final_position()是否在target_desired_distance内接近target_positionis_target_reached()bool是否已进入目标范围。目标未必总能到达但最终位置通常可达参见get_final_position()set_navigation_map(navigation_map)void设置节点使用的导航地图 RID并同步更新 NavigationServer 上的代理set_velocity_forced(velocity)void替换避障模拟内部速度传送后应在同一帧使用get/set_avoidance_layer_value(layer_number)bool/void按 132 逐位读写avoidance_layersget/set_avoidance_mask_value(mask_number)bool/void按 132 逐位读写avoidance_maskget/set_navigation_layer_value(layer_number)bool/void按 132 逐位读写navigation_layers调试可视化debug_enabled true时为该代理显示调试可视化。debug_use_custom true时使用debug_path_custom_color默认白色Color(1, 1, 1, 1)与debug_path_custom_point_size默认4.0替代全局调试颜色/点尺寸。更多导航调试工具参见 navigation_debug_tools.rst。实战脚本模板三种常见 3D 节点官方教程 navigation_using_navigationagents.rst 为常见父节点提供了完整模板。以CharacterBody3DGDScript为例extends CharacterBody3D export var movement_speed: float 4.0 onready var navigation_agent: NavigationAgent3D get_node(NavigationAgent3D) func _ready() - void: navigation_agent.velocity_computed.connect(Callable(_on_velocity_computed)) func set_movement_target(movement_target: Vector3): navigation_agent.set_target_position(movement_target) func _physics_process(delta): # 地图从未同步且为空时不要查询 if NavigationServer3D.map_get_iteration_id(navigation_agent.get_navigation_map()) 0: return if navigation_agent.is_navigation_finished(): return var next_path_position: Vector3 navigation_agent.get_next_path_position() var new_velocity: Vector3 global_position.direction_to(next_path_position) * movement_speed if navigation_agent.avoidance_enabled: navigation_agent.set_velocity(new_velocity) else: _on_velocity_computed(new_velocity) func _on_velocity_computed(safe_velocity: Vector3): velocity safe_velocity move_and_slide()Node3D版本无物理、直接移动的区别在于保存physics_delta并在_on_velocity_computed中用global_position global_position.move_toward(global_position safe_velocity, physics_delta * movement_speed)移动。RigidBody3D版本则把safe_velocity赋给linear_velocity让物理引擎接管。C# 版本在官方教程中同样齐全VelocityComputed事件、GlobalPosition.MoveToward、MoveAndSlide()等一一对应。关键结论与性能提醒NavigationAgent3D 是辅助节点而非必需品其全部功能都可以用脚本 NavigationServer3D 直接调用替代更进阶的用法可参考 navigation_using_navigationpathqueryobjects.rst。避障不参与寻路避障应视为无法重新烘焙进导航网格的持续移动物体的补充手段avoidance_enabled只在确实需要时开启否则会引入显著 CPU 开销。RVO 隐含自然行为假设它假设代理在相遇时可被分配合理的通行侧。因此非常刻板的避障测试场景通常会失败——例如两个代理以完美相反的速度正对相向而行会因无法分配通行侧而卡住。每个代理配置独立的寻路/避障参数不同体型、不同通行权限的角色应结合导航层、不同 agent_radius 烘焙的导航网格与独立导航地图来区分而不是依赖单一属性硬凑。相关阅读Using NavigationAgents 教程、NavigationServer3D 类参考、NavigationObstacle3D、NavigationPathQueryParameters3D 枚举、Navigation 教程总览。赞分享文档教程游戏开发【免费下载链接】godot-docsGodot Engine official documentation项目地址https://gitcode.com/GitHub_Trending/go/godot-docs点击查看免费下载相关推荐Godot 3D 导航寻路NavigationDemo 详解NavigationAgent3D、NavigationServer3D 与 3D 路径跟随实现Godot 3D 导航寻路NavigationDemo 详解NavigationAgent3D、NavigationServer3D 与 3D 路径跟随实示例工程Godot 2D 路径跟随系统 Path2D 全面解析Curve2D 路径定义与 PathFollow2D 实战指南Godot 2D 路径跟随系统 Path2D 全面解析Curve2D 路径定义与 PathFollow2D 实战指南 Path2D 是 Godot 引擎中承载文档教程游戏开发Godot EngineAI路径跟随让角色沿路径移动Godot EngineAI路径跟随让角色沿路径移动 在游戏开发中角色自动沿指定路径移动是常见需求无论是NPC巡逻、玩家导航还是敌人追击。Godot En游戏开发图形学跨平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考