当前位置:   article > 正文

Unity如何判断对象是否已被Destroy_unity 判断物体是否正在destroy

unity 判断物体是否正在destroy

熟悉了cocos语法的都知道cc.isValid这个api可以判断节点/组件是否可用(是否已被销毁)

而Unity中却没有这样的API,往往使用==null来进行判断

那么==null到底如何来判断呢?

Part 1

        public int numTest = 998;
        public void Print()
        {
            Debug.Log("TestScriptOfBilly.Print this.gameObject.name " + this.gameObject.name);  //0
            Destroy(gameObject);
            Debug.Log("TestScriptOfBilly this == null 1st " + (this == null).ToString());       //1
            Debug.Log("TestScriptOfBilly this.numTest 1st " + numTest);                         //2
            Debug.Log("TestScriptOfBilly this.gameObject.name 1st " + this.gameObject.name);    //3
            DOVirtual.DelayedCall(1.0f, () =>
            {
                Debug.Log("TestScriptOfBilly DelayedCall callback this == null 2nd " + (this == null).ToString());  //4
                Debug.Log("TestScriptOfBilly DelayedCall callback this.numTest 2nd " + numTest);                    //5
                Debug.Log("TestScriptOfBilly DelayedCall callback this.gameObject.name 2nd" + this.gameObject.name);//6
            });
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这里插入图片描述

结合log可以发现

Destroy之后当前帧内this(MonoBehaviour)与gameObject都未被立即销毁

1,2,3三句log可以佐证

而在延迟回调里面(Destroy之后的帧)

4,5,6三句log十分"诡异"

第4句this==null已经变为了true

第5句却仍然能访问到this.numTest的值998

第6句访问gameObject直接报错

这里大胆推测,this其实并不是null

而是由于

UnityEngine.Object

public static bool operator ==(Object x, Object y);

这里重写了运算符,把已经销毁的Object根据销毁标记在与null判定相等时返回了true

Part 2
为此我们再做一个实验

       void testValid()
        {
            TestScriptOfBilly tsob = imgTest.GetComponent<TestScriptOfBilly>();
            Destroy(imgTest);
            DOVirtual.DelayedCall(1.0f, () =>
            {
                Debug.Log("DelayedCall callback tsob == null " + (tsob == null).ToString());
                Debug.Log("DelayedCall callback tsob.numTest 1st " + tsob.numTest);
                tsob = null;
                Debug.Log("DelayedCall callback tsob.numTest 2nd " + tsob.numTest);
            });
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

可以清晰的看到

同样判空==true

1st输出了998

tsob=null赋值之后2nd未输出直接报错

因为索引null的属性报错是必然的

Part 3
再测试一下DestroyImmediate

       void testValid()
        {
            TestScriptOfBilly tsob = imgTest.GetComponent<TestScriptOfBilly>();
            DestroyImmediate(imgTest);
            Debug.Log("testValid imgTest == null " + (imgTest == null).ToString());
            Debug.Log("testValid tsob == null " + (tsob == null).ToString());
            Debug.Log("testValid tsob.numTest " + tsob.numTest);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

结果与预期一致 DestroyImmediate使判空可以立即生效不必等到下一帧

其余逻辑与Destroy一致

Part 4
最后终极测试一下,通过两个文件来操作

TestScriptOfBilly.cs

        public void DoDestroy()
        {
            Debug.Log("TestScriptOfBilly.Print and DestroyImmediate");
            DestroyImmediate(gameObject);
        }
  • 1
  • 2
  • 3
  • 4
  • 5

TestSceneOfBilly.cs

        void testValid()
        {
            TestScriptOfBilly tsob = imgTest.GetComponent<TestScriptOfBilly>();
            tsob.DoDestroy();
            Debug.Log("testValid imgTest == null " + (imgTest == null).ToString());
            Debug.Log("testValid tsob == null " + (tsob == null).ToString());
            Debug.Log("testValid tsob.numTest " + tsob.numTest);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

结果与之前一致

侧面说明Destroy并未在销毁后对参数赋值为null

无论tsob还是前面的this都是在==操作符重载里根据内部状态来判定的

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/332915
推荐阅读
相关标签
  

闽ICP备14008679号