在Unity3D 2019.3.05f中,如何检查一个GameObject是否在检视面板中被分配?

5

问题:

如何在Unity3D中检查MonoBehaviour的公共gameObject是否已经在检视面板中分配,因为空值比较(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;
 }

该方法可在代码中的任何可空对象上调用,例如在此简单的Monobehaviour中:
public class TestScript : MonoBehaviour
{
    public GameObject testObject = null;

    public void TestObject()
    {
        var result = testObject.IsNull("Error message");
        Debug.Log(result);
        Debug.Log(testObject);
    }
}

对于大多数用例,我的方法完美地工作并且在编码/调试期间节省了很多时间。但我现在的问题是,如果我没有在编辑器中签署“testObject”,我的测试将无法正常工作,因为testObject似乎不为空,但它也无法使用,因为它未被分配。在这种情况下,控制台输出如下:
False null
当相应的对象未在Unity检查器中分配时,为什么(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;
        }
    }
1个回答

10
Unity有一个自定义的等式运算符“==”实现(参见Custom == operator, should we keep it?),这经常导致混淆/意外行为。
即使UnityEngine.Object的值等于null,有时它也不等于null。Object仍然在其中存储一些元数据,例如,您会得到MissingReferenceException而不是通常的NullReferenceException,因为Unity实现了一些自定义异常,这些异常通常包含更多关于为什么该值等于null的详细信息。
特别是因为
public GameObject testObject = null;

如果一个字段是public类型,它会自动被序列化,因此你赋值为null的值将在序列化期间被覆盖。


UnityEngine.Objectbool类型的隐式转换运算符,GameObject继承自它。

对象是否存在?

与其直接使用== 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;
}

对于任何引用类型都适用的一般方法,您可以使用类似以下内容的东西:

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

1
谢谢,这很不错。谢谢你。有没有一种方法可以以某种方式重载此方法,使其也适用于所有非Unity引擎对象,然后我可以以“经典”方式检查所有其他可空对象是否为空? - DaveM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接