You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity报错“GameObject类型对象已销毁但仍被访问”如何修复

错误原因
  • 核心逻辑错误:你在OnCollisionExit中同时执行了**立即调用Fall()和延迟0.2秒调用Fall()**两次操作,第二次执行Fall()时,对象可能已经被标记为待销毁,重复调用Destroy也会触发访问异常。
  • 无状态校验:没有标记平台是否已经触发下落逻辑,物理碰撞的抖动可能导致OnCollisionExit被触发多次,反复调用Fall()和Invoke,后续调用就会访问已经销毁/待销毁的对象。
  • 没有提前缓存组件:每次调用Fall()都执行GetComponent<Rigidbody>(),如果组件已经被销毁、或者对象已被标记为销毁,就会触发MissingReference异常。
修复步骤
  1. 新增一个布尔变量标记平台是否已经触发下落,避免重复执行逻辑
  2. 提前在Awake()中缓存Rigidbody组件,避免反复调用GetComponent
  3. 修正重复调用Fall()的逻辑:如果需要玩家离开平台0.2秒后再下落,就只保留延迟调用,删除立即调用的Fall(),如果需要立刻下落则反过来调整
  4. 执行下落逻辑后清空所有待执行的Invoke调用,避免对象销毁前还有排队的方法调用
  5. 所有访问组件/对象的位置加判空校验
修复后代码
// 标记是否已经触发下落
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:45:03