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

Unity中OnDisable取消事件订阅失效引发MissingReferenceException问题咨询

问题分析与解决方案

首先,你的问题核心在于Unity对象销毁与C#委托强引用之间的冲突,即使你在OnDisable里执行了取消订阅,已销毁对象的方法引用可能仍然残留在委托中,导致事件触发时调用了无效对象的方法。下面拆解原因并给出可行的解决方案:

为什么OnDisable执行了但订阅没完全清除?

C#的委托是强引用,也就是说,只要委托里还保留着对象方法的引用,即使Unity已经标记该对象为“已销毁”,托管堆里的对象实例不会立即被GC回收。如果场景加载时旧对象的OnDisable取消订阅操作没有完全移除委托中的引用(比如出现了重复订阅的情况,或者Unity的对象销毁流程与委托清理的时间差),事件触发时就会调用这个“僵尸对象”的方法,从而抛出MissingReferenceException。

另外,你提到OnDisable确实被调用了,但这里要注意:OnDisable会在对象失活或销毁时都触发,如果你的对象之前被多次SetActive(false/true),可能出现订阅次数多于取消次数的情况,导致委托里残留了多余的引用。

为什么this != null有用但gameObject == null无效?

Unity对MonoBehaviour和GameObject重载了==运算符,它不是检查托管堆的引用是否为空,而是检查对象的native实例是否还存在:

  • 对于this != null:当MonoBehaviour被销毁后,Unity的自定义==会直接检测到native实例已失效,返回false,所以这个检查能生效。
  • 对于gameObject == null:gameObject是MonoBehaviour的属性,当对象被销毁后,访问gameObject会返回一个已标记为销毁的GameObject实例。由于Unity的native状态更新可能有延迟(比如场景加载后同一帧内,GameObject的销毁状态还没同步到运算符检查),此时gameObject == null可能返回true也可能返回false,稳定性远不如直接检查this或使用官方的IsDestroyed()方法。

可行的解决方案

1. 使用IsDestroyed()做最可靠的空检查

Unity提供了MonoBehaviour.IsDestroyed()方法,专门用来判断对象是否已经被销毁,比this != null更明确可靠:

private void AdjustGraphics() { 
    if (!IsDestroyed()) 
        gameObject.SetActive(GameSettings.Graphics >= requiredQuality); 
}

2. 在OnDestroy中额外添加取消订阅的保险

场景加载时对象会被销毁,OnDestroy一定会执行。在这个生命周期函数里再执行一次取消订阅,即使之前OnDisable已经执行过,重复取消也不会报错,能彻底避免委托里残留无效引用:

private void OnEnable() { 
    AdjustGraphics(); 
    GameSettings.GraphicsChanged += AdjustGraphics; 
}

private void OnDisable() { 
    GameSettings.GraphicsChanged -= AdjustGraphics; 
}

private void OnDestroy() {
    // 双重保险,确保引用被移除
    GameSettings.GraphicsChanged -= AdjustGraphics;
}

3. 避免重复订阅(防患于未然)

如果你的对象可能被多次启用/禁用,最好在订阅前先取消一次,防止出现重复订阅的情况:

private void OnEnable() { 
    AdjustGraphics(); 
    // 先取消再订阅,避免重复订阅
    GameSettings.GraphicsChanged -= AdjustGraphics;
    GameSettings.GraphicsChanged += AdjustGraphics; 
}

这样即使OnDisable没被正确调用(比如极端情况下的异常流程),也能保证每次启用时只有一个有效的订阅。

内容的提问来源于stack exchange,提问作者Dave

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:50:18