如果请求的组件未附加到对象,我对GetComponent
的返回值感到困惑。根据Unity文档,GetComponent
应该返回null。但是,似乎正在发生的事情是GetComponent
返回所请求类型的“null”对象,而不是值null
。
在此示例中,我的游戏对象没有附加CircleCollider2D
。当我在第CircleCollider2D x = GetComponent<CircleCollider2D>();
行I get this result
为什么返回的值不是null
?
编辑:
Here's a full screenshot of the code and the values in the debugger.
另一个编辑:
Unity是否已重载==
运算符以使GetComponent
始终返回一个对象,但该对象可以具有内部“null”状态,与{{1}相比时返回true }?我可以在null
命名空间
UnityEngine
答案 0 :(得分:5)
似乎GetComponent<T>()
没有返回 TRUE null
。相反,它返回新T,其默认值在使用任何空字段时触发MissingComponentException
。 GetInstanceID()
和GetHashCode()
有效,因为它们只使用设置为默认值为0的int m_InstanceID
。不确定ToString()
如何工作但在{{1}时可能会返回"null"
}}
证明:
m_InstanceID == 0
结果:
void Start()
{
CircleCollider2D getComponent = GetComponent<CircleCollider2D>();
CircleCollider2D empty = null;
CircleCollider2D newCC = new CircleCollider2D();
Debug.LogFormat("getComponent.GetInstanceID() {0}", getComponent.GetInstanceID());
Debug.LogFormat("newCC.GetInstanceID() {0}", newCC.GetInstanceID());
try
{
Debug.LogFormat("empty.GetInstanceID() {0}", empty.GetInstanceID());
}
catch (System.NullReferenceException e)
{
Debug.Log("empty.GetInstanceID() doesnt work, im true null");
}
try
{
string t = getComponent.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("getComponent fires {0} when any field is null",
e.ToString()));
}
try
{
string t = newCC.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("newCC fires {0} when any field is null",
e.ToString()));
}
}
此外:
getComponent.GetInstanceID() 0
newCC.GetInstanceID() 0
empty.GetInstanceID() doesnt work, im true null
getComponent fires UnityEngine.MissingComponentException
newCC fires System.NullReferenceException
为什么getComponent.GetHashCode() = 0
getComponent.ToString() = "null"
是真的?通常它只是:
getComponent == null
在`getComponent.GetInstanceID() == otherComponent.GetInstanceID()`
案例中,它是:
o == null
所以我猜InstanceID = 0的对象永远不会存在。 如果您想了解更多信息,请搜索反编译的UnityEngine / UnityEngine / Object.cs。
答案 1 :(得分:2)
Unity是否重载了==运算符
Tldr:是。
为什么返回的值不为空?
根据Custom == operator, should we keep it?:
当MonoBehaviour有字段时,仅在编辑器中,我们不设置 那些字段为“真正的空”,但是为“假空”对象。
为什么呢?根据那篇文章,基本上有两个原因:
在编辑器模式下:获取有关调用的更多上下文信息,因此如果您有异常,您将能够知道哪个对象是原因。
来自UnityEngine.Object
的每一个都包含在C#对象中,以保持对Unity C / C ++ GameEngine对象的引用。在编辑器/代码中,我们使用C#元素,但这些只是对“真正的”c ++对象的引用。现在,显式处理那些“真正的”c ++对象的生命周期(如果你将要销毁C ++对象的destroy
并释放它将分配的内存)但是当垃圾时C#对象将被完全销毁收藏家决定释放那段记忆。因此,您将拥有一个指向空C ++对象的非空C#对象。使用此假null 技巧,您将知道此特定C#对象是null
,因为在C ++端它被销毁。
如果你有一个单身并且if (sm_Instance == null)
没有按预期工作,这也很重要,你可以使用:if (EqualityComparer<T>.Default.Equals(sm_Instance, null))
instad。
编辑:如果您的单身人士使用泛型并且您的类型约束为class
public class Singleton<T> where T : class {
这将导致使用类对象的==
运算符,即使您的Singleton是GameEngine对象也是如此。一个解决方案?您可以使用class
代替UnityEngine.Object
,而不是:{/ p>
public class Singleton<T> where T : UnityEngine.Object {
相关主题:
https://forum.unity3d.com/threads/null-check-inconsistency-c.220649/#post-1775701
Ps:如果你去UnityEngine.Object程序集,你将能够看到重载:
几乎在最后......
答案 2 :(得分:0)
GetComponent
应返回类型&#39;对象. Hence it is not expected to return "null" rather ~null
的对象是预期值。也许这种奇怪的行为应该报告给unity3d
,