Unity脚本导致编辑器无响应卡顿问题排查求助
Unity脚本卡顿问题排查
问题描述
我写了一个脚本,功能是先禁用所有名为“target”的对象,再随机激活其中一个,让NavMeshAgent移动到该目标;当NavMeshAgent到达当前激活的目标后,会禁用这个目标并切换激活新的随机目标。但进入PlayMode测试时,Unity直接卡顿、无响应,只能用任务管理器强制关闭;停用这个脚本后游戏运行完全正常。之前还出现过错误提示:LS Allocator ALLOC_TEMP_TLS, underlying allocator ALLOC_TEMP_MAIN has unfreed allocations, size 560,但卡顿后这个错误就不再出现了。我附上了初始脚本和优化后的脚本,希望能找出卡顿的原因,我编程经验不多。
初始脚本
using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; public class TargetManager : MonoBehaviour { public Transform[] targets; private void Start() { // 获取所有子物体的Transform targets = GetComponentsInChildren<Transform>(); // 移除第一个元素(自身Transform) targets = targets.Skip(1).ToArray(); // 初始时禁用所有目标 foreach (Transform target in targets) { target.gameObject.SetActive(false); } // 激活随机目标 ActivateRandomTarget(); } public void ActivateRandomTarget() { // 禁用所有目标 foreach (Transform target in targets) { target.gameObject.SetActive(false); } // 随机选择索引并激活目标 int randomIndex = Random.Range(0, targets.Length); targets[randomIndex].gameObject.SetActive(true); } }
优化后脚本
using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; public class TargetManager : MonoBehaviour { public List<GameObject> targets = new List<GameObject>(); private int currentTargetIndex = -1; private void Start() { // 初始时禁用所有目标 foreach (GameObject target in targets) { target.SetActive(false); } // 激活随机目标 ActivateRandomTarget(); } public void ActivateRandomTarget() { if (targets.Count == 0) { Debug.LogWarning("未找到目标,请在Inspector中添加目标对象到列表。"); return; } // 禁用当前激活的目标 if (currentTargetIndex >= 0 && currentTargetIndex < targets.Count) { targets[currentTargetIndex].SetActive(false); } // 随机选择索引并激活新目标 int randomIndex = Random.Range(0, targets.Count); targets[randomIndex].SetActive(true); // 更新当前目标索引 currentTargetIndex = randomIndex; } }
卡顿原因分析
初始脚本的核心问题:
- 若
ActivateRandomTarget()被高频调用(比如NavMeshAgent到达逻辑错误,导致每帧都调用),每次调用都要遍历所有目标执行SetActive(false),大量的对象激活/禁用操作会触发Unity频繁刷新对象状态,直接阻塞主线程。 targets.Skip(1).ToArray()每次都会创建新数组,增加GC压力,但这一般不会直接导致卡死。
- 若
优化后脚本的潜在残留问题:
优化后的脚本已经减少了SetActive的调用次数(只禁用当前目标),但如果NavMeshAgent的到达检测逻辑有问题,导致ActivateRandomTarget()被无限循环调用(比如目标位置与Agent位置重叠,触发到达后立刻切换新目标,新目标又瞬间被判定为到达),依然会占满主线程导致卡顿。关于内存分配错误:
那个unfreed allocations错误属于Unity内部临时内存未释放,和你的脚本关联不大,卡顿后错误消失是因为Unity卡死时无法输出日志。
解决建议
- 检查到达触发逻辑:不要在
Update里每帧调用ActivateRandomTarget(),改用NavMeshAgent的isStopped状态,或者设置合理的距离阈值(比如距离目标大于0.5f时才移动,到达后仅调用一次切换方法)。 - 添加调试日志:在
ActivateRandomTarget()开头加Debug.Log("切换目标"),查看方法调用频率,若每秒调用几十次以上,说明触发逻辑有问题。 - 确认目标列表赋值:在Inspector中确保
targets列表正确添加了所有目标对象,避免空列表的无效调用。 - 避免重复切换相同目标:可以在随机选索引时,判断是否和当前索引相同,若相同则重新随机,减少不必要的
SetActive操作。
内容的提问来源于stack exchange,提问作者JoseaRegbla
相关产品推荐
相关产品推荐

