Unity中首路径节点销毁后Agent无法更新移动目标的问题
问题根因
- 每帧调用
FindGameObjectsWithTag获取的对象数组,Unity不保证返回顺序和你预期的路径顺序一致,不会自动实现「第一个节点销毁后下一个自动顶到索引0」的效果,甚至可能返回已经销毁但未被引擎回收的空对象。 - 已经挂载
NavMeshAgent组件但完全没有调用其导航接口,自行编写的MoveTowards混合Lerp移动逻辑存在缺陷,写的for循环全程只读取trailLists[0],循环无实际作用,也没有添加「是否到达当前目标」的判定逻辑,Agent抵达首个点后自然卡住。 - 未做空引用过滤:路径节点销毁后列表中会存储null值,此时访问
trailLists[0].transform会直接抛出空引用异常,后续逻辑全部中断,Agent不会再响应移动指令。
修复方案
核心逻辑调整:初始加载一次路径节点列表,每帧仅清理列表中已销毁的空节点,始终将列表首位节点作为当前移动目标,正确调用NavMeshAgent接口完成导航,节点销毁后会被自动移出列表,下一个节点自动成为新的首位目标,无需手动维护索引。
修复后完整代码:
using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using System.Linq; public class MoveToTrail : MonoBehaviour { [Header("路径配置")] [SerializeField] private string trailTag = "Trail"; [SerializeField] private float reachThreshold = 0.3f; // 到达目标的判定距离 [SerializeField] private float moveSpeed = 5f; private List<GameObject> trailList = new List<GameObject>(); private NavMeshAgent navMeshAgent; private void Awake() { navMeshAgent = GetComponent<NavMeshAgent>(); navMeshAgent.speed = moveSpeed; // 初始加载所有路径节点 RefreshTrailList(); } private void Update() { // 清理列表中已销毁的空节点 CleanDestroyedTrail(); // 无剩余路径则停止移动 if (trailList.Count == 0) { navMeshAgent.isStopped = true; return; } // 取首位节点为当前目标 GameObject currentTarget = trailList[0]; // 未到达目标则持续导航 if (Vector3.Distance(transform.position, currentTarget.transform.position) > reachThreshold) { navMeshAgent.isStopped = false; navMeshAgent.SetDestination(currentTarget.transform.position); } } // 刷新路径节点列表 private void RefreshTrailList() { trailList = GameObject.FindGameObjectsWithTag(trailTag) .Where(go => go != null) .ToList(); // 若返回的节点顺序和预期路径不一致,在此处添加自定义排序逻辑,例如按坐标、节点命名序号排序 } // 移除列表中已销毁的节点 private void CleanDestroyedTrail() { for (int i = trailList.Count - 1; i >= 0; i--) { if (trailList[i] == null) { trailList.RemoveAt(i); } } } }
关键修改点
- 移除无意义的每帧全量节点查找和无效for循环,仅在初始时加载一次路径列表,每帧只做已销毁节点清理,性能开销更低。
- 正确调用
NavMeshAgent.SetDestination实现导航,无需自行编写位置插值逻辑,引擎自动处理寻路、避障、移动平滑度。 - 新增到达距离判定,当前首位节点未销毁、Agent未抵达目标点时持续向该点移动;节点销毁后会被自动移出列表,下一个节点自动成为新目标,无需手动切换索引。
- 新增空引用防护,避免访问已销毁对象的组件导致脚本异常中断。
注意:如果
FindGameObjectsWithTag返回的节点顺序和你设计的路径走向不符,必须在RefreshTrailList方法中添加自定义排序规则,比如按路径节点的坐标排序、按节点名称的数字序号排序,确保列表顺序和路径顺序完全一致。
内容的提问来源于stack exchange,提问作者Tedtedted
相关产品推荐
相关产品推荐

