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

Unity中订阅事件时Destroy(gameObject)仅生效一次的问题求助

解决Unity中静态事件订阅引发的MissingReferenceException问题

首先咱们来理清楚问题根源:你用Lambda表达式订阅了静态事件OnChangeScene,第一次点击触发事件时,Destroy(gameObject)成功销毁了当前的Animal对象。但静态事件的生命周期和整个程序绑定,不会自动移除已销毁对象的订阅——也就是说,这个Lambda还挂在事件列表里。下次点击触发事件时,代码会尝试执行这个已经失效的Lambda,而此时Animal对象已经被销毁,访问它的gameObject就会抛出那个MissingReferenceException。

接下来给你两种可行的解决方案:

方案一:对象销毁前取消订阅(推荐)

因为Lambda表达式是匿名的,直接取消订阅需要先把它保存为一个变量。修改第二个脚本的代码如下:

// 先保存Lambda的引用,方便后续取消订阅
private Action _sceneChangeHandler;

private void Start()
{
    _sceneChangeHandler = () => Destroy(gameObject);
    MoveButton.OnChangeScene += _sceneChangeHandler;
}

private void OnDestroy()
{
    // 对象销毁时,从静态事件中移除订阅
    if (_sceneChangeHandler != null)
    {
        MoveButton.OnChangeScene -= _sceneChangeHandler;
    }
}

这样一来,当Animal对象被销毁时,OnDestroy会自动把订阅从静态事件里移除,后续触发事件时就不会再执行这个无效的Lambda了,也就不会报错。

方案二:在Lambda中增加有效性检查

如果你暂时不想修改订阅逻辑,也可以在Lambda里先判断对象是否还能被访问:

private void Start()
{
    MoveButton.OnChangeScene += () => 
    {
        // 先检查当前对象是否未被销毁
        if (this != null && gameObject != null)
        {
            Destroy(gameObject);
        }
    };
}

不过这种方法只是避免了报错,失效的订阅仍然会留在静态事件列表里,长期下来可能造成内存浪费,所以更推荐方案一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:03:30