物体的 activeInHierarchy = false 或脚本的 enable = false 时将物体销毁,OnDestroy 仍被调用
看到一个人说 OnDestroy 有深坑
好在 Unity 给我们留下了许多实用的生命周期方法……以及一堆坑!
一个错误的(至少是有隐患的)做法是在 MonoBehavior.OnDestroy 方法中退订事件。因为当某个物体在场上处于未启用状态时被销毁,它的 OnDestroy 是不会被调用的!!!
具体而言是在以下几种操作时 OnDestroy 不会调用:
对该物体或其父物体调用 SetActive(false);
对该脚本设置了 enabled = false;
在运行时的 Inspector 中禁用了组件或其附属物体(或父物体)
我遇到的问题是,我订阅事件的物体处于未启用状态,此时加载切换至另一场景(自然销毁了所有订阅方,但OnDestroy 未被调用,即未正常退订事件)。另一方面,我的广播方是存在于全局跨场景的对象,因此当它再广播该事件时,残余的事件订阅引发了一连串的错误,查错的时候啪的一下很快啊,一天又过去了
————————————————
版权声明:本文为CSDN博主「mkr67n」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
但是我又看到一个人是得出了 OnDestroy 不会受这些情况影响的结论
于是我自己试了一下
测试类
新建一个测试类 TestMono.cs
public class TestMono : MonoBehaviour
{
private void OnDestroy()
{
print("OnDestroy!");
}
}
在其他任意 Mono 类里面测试这个 TestMono
1. 在挂载测试 Mono 的物体被禁用时,将该物体销毁
private void Start()
{
StartCoroutine(TestCo());
}
private IEnumerator TestCo()
{
GameObject testGameObject = new GameObject();
testGameObject.AddComponent<TestMono>();
testGameObject.SetActive(false);
yield return new WaitForSeconds(5f);
Destroy(testGameObject);
}
结果是测试 Mono 的 OnDestroy 被调用
2. 在挂载测试 Mono 的物体的父物体被禁用时,将该物体销毁
private IEnumerator TestCo()
{
GameObject testGameObject = new GameObject();
TestMono testMono = testGameObject.AddComponent<TestMono>();
GameObject testParent = new GameObject();
testGameObject.transform.parent = testParent.transform;
testParent.SetActive(false);
yield return new WaitForSeconds(5f);
Destroy(testGameObject);
}
结果是测试 Mono 的 OnDestroy 被调用
综合 1 2,挂载测试 Mono 的物体的 activeInHierarchy = false 时,删去挂载测试 Mono 的物体, 测试 Mono 的 OnDestroy 会被调用
3. 在挂载测试 Mono 的物体的 Mono 脚本被禁用时,将该物体销毁
private IEnumerator TestCo()
{
GameObject testGameObject = new GameObject();
TestMono testMono = testGameObject.AddComponent<TestMono>();
//testGameObject.SetActive(false);
testMono.enabled = false;
yield return new WaitForSeconds(5f);
print(testMono.enabled);
Destroy(testGameObject);
}
结果是测试 Mono 的 OnDestroy 被调用
综合 1 2 3,我感觉