检查是否在 Unity3D 2019.3.05f 中的检查器中分配了 GameObject

Dav*_*veM 4 c# isnull unity-game-engine

题:

如何在 Unity3D 的检查器中检查 MonoBehaviour 的公共游戏对象是否已分配,因为 null 的比较(object==null)失败。

具体例子:

我即将为 Unity3D 编写一个通用方法,该方法可以在任何可空对象上调用。它检查对象是否为空,如果是,则写入一个Debug.LogError(customMessage). 该方法如下所示:

 public static bool IsNull<T>([CanBeNull] this T myObject, string message = "")
 {
     if (myObject!= null) return false;
     Debug.LogError("The object is null! " + message);
     return true;
 }
Run Code Online (Sandbox Code Playgroud)

该方法可以在代码中的任何位置的任何可为空对象上调用,例如在这个简单的 Monobehaviour 中:

public class TestScript : MonoBehaviour
{
    public GameObject testObject = null;

    public void TestObject()
    {
        var result = testObject.IsNull("Error message");
        Debug.Log(result);
        Debug.Log(testObject);
    }
}
Run Code Online (Sandbox Code Playgroud)

对于大多数用例,我的方法可以完美运行并在编码/调试期间节省大量时间。但我现在的问题是,如果我没有在编辑器中签署“testObject”,我的测试将无法工作,因为 testObject 似乎不为空,但它也无法使用,因为它没有被分配。在这种情况下,控制台输出是:


怎么会(myObject == null)是假的,而只要未在统一检查器中分配相应的对象,它就Debug.Log(testObject)会给我null

编辑/解决方案: 感谢 derHugo 的帮助,我最终得到了这个通用代码片段:

 public static bool IsNull<T>(this T myObject, string message = "") where T : class
    {
        switch (myObject)
        {
            case UnityEngine.Object obj when !obj:
                Debug.LogError("The object is null! " + message);
                return true;
            case null:
                Debug.LogError("The object is null! " + message);
                return true;
            default:
                return false;
        }
    }
Run Code Online (Sandbox Code Playgroud)

der*_*ugo 7

Unity 具有相等==运算符的自定义实现(请参阅自定义 == 运算符,我们应该保留它吗?这通常会导致混淆/意外行为。

即使 anUnityEngine.Object的值等于 null它有时也不是== nullObject而是仍然在其中存储一些元数据,例如,您会得到一个MissingReferenceException,而不是通常的,NullReferenceException因为 Unity 实现了一些自定义异常,这些异常通常包含更多关于为什么值等于 的详细信息null

特别是从

public GameObject testObject = null;
Run Code Online (Sandbox Code Playgroud)

是一个public字段,它会自动序列化,因此null您分配给它的值在序列化过程中无论如何都会被覆盖。


UnityEngine.ObjectGameObject导出从具有一个隐含的操作者bool

对象是否存在?

== null您应该检查,而不是直接比较

public static bool IsNull<T>(this T myObject, string message = "") where T : UnityEngine.Object
{
    if(!myObject)
    {
        Debug.LogError("The object is null! " + message);
        return false;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)

对于适用于任何引用类型的通用方法,您可以使用类似的方法

public static bool IsNull<T>(this T myObject, string message = "") where T : class
{
    if (myObject is UnityEngine.Object obj)
    {
        if (!obj)
        {
            Debug.LogError("The object is null! " + message);
            return false;
        }
    }
    else
    {
        if (myObject == null)
        {
            Debug.LogError("The object is null! " + message);
            return false;
        }
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)