GetComponent返回“null”而不是null

时间:2017-07-08 22:10:56

标签: c# unity3d

如果请求的组件未附加到对象,我对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

3 个答案:

答案 0 :(得分:5)

似乎GetComponent<T>()没有返回 TRUE null。相反,它返回新T,其默认值在使用任何空字段时触发MissingComponentExceptionGetInstanceID()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程序集,你将能够看到重载:

UnityEngine.Object

几乎在最后......

Overload

答案 2 :(得分:0)

GetComponent应返回类型&#39;对象. Hence it is not expected to return "null" rather ~null的对象是预期值。也许这种奇怪的行为应该报告给unity3d