Unity报错“GameObject类型对象已销毁但仍被访问”如何修复
错误原因
- 核心逻辑错误:你在
OnCollisionExit中同时执行了**立即调用Fall()和延迟0.2秒调用Fall()**两次操作,第二次执行Fall()时,对象可能已经被标记为待销毁,重复调用Destroy也会触发访问异常。 - 无状态校验:没有标记平台是否已经触发下落逻辑,物理碰撞的抖动可能导致
OnCollisionExit被触发多次,反复调用Fall()和Invoke,后续调用就会访问已经销毁/待销毁的对象。 - 没有提前缓存组件:每次调用
Fall()都执行GetComponent<Rigidbody>(),如果组件已经被销毁、或者对象已被标记为销毁,就会触发MissingReference异常。
修复步骤
- 新增一个布尔变量标记平台是否已经触发下落,避免重复执行逻辑
- 提前在
Awake()中缓存Rigidbody组件,避免反复调用GetComponent - 修正重复调用
Fall()的逻辑:如果需要玩家离开平台0.2秒后再下落,就只保留延迟调用,删除立即调用的Fall(),如果需要立刻下落则反过来调整 - 执行下落逻辑后清空所有待执行的Invoke调用,避免对象销毁前还有排队的方法调用
- 所有访问组件/对象的位置加判空校验
修复后代码
// 标记是否已经触发下落 private bool hasFallen = false; // 提前缓存刚体组件 private Rigidbody rb; private void Awake() { rb = GetComponent<Rigidbody>(); } private void OnCollisionExit(Collision collision) { // 已经触发过下落、刚体不存在、碰撞对象不是玩家三种情况直接返回 if (hasFallen || !rb || !collision.gameObject.CompareTag("Player")) return; // 需要玩家离开后立刻下落就保留这行,删除下面的Invoke // Fall(); // 需要延迟0.2秒下落就只保留这行Invoke,删除上面的立即调用 Invoke("Fall", 0.2f); } void Fall() { // 二次校验,避免访问已销毁的对象/组件 if (hasFallen || !rb || !gameObject) return; hasFallen = true; rb.isKinematic = false; Destroy(gameObject, 1f); // 清空所有待执行的Invoke,避免残留调用 CancelInvoke(); }
内容的提问来源于stack exchange,提问作者Talon Tài
相关产品推荐
相关产品推荐

