赞
踩
熟悉了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都是在==操作符重载里根据内部状态来判定的
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。