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
            });
        }

 

結合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);
            });
        }

 

可以清晰的看到

同樣判空==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);
        }

 

結果與預期一致 DestroyImmediate使判空可以立即生效不必等到下一幀

其余邏輯與Destroy一致

 

Part 4

最后終極測試一下,通過兩個文件來操作

TestScriptOfBilly.cs
        public void DoDestroy()
        {
            Debug.Log("TestScriptOfBilly.Print and DestroyImmediate");
            DestroyImmediate(gameObject);
        }
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);
        }

結果與之前一致

側面說明Destroy並未在銷毀后對參數賦值為null

無論tsob還是前面的this都是在==操作符重載里根據內部狀態來判定的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM