【问题标题】:Check if a GameObject has been assigned in the inspector in Unity3D 2019.3.05f检查是否已在 Unity3D 2019.3.05f 的检查器中分配了游戏对象
【发布时间】:2020-02-12 13:12:42
【问题描述】:

问题:

如何检查 MonoBehaviour 的公共游戏对象是否已在检查器中分配 Unity3D,因为 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;
 }

可以在代码中的任何位置对任何可为空的对象调用该方法,例如在这个简单的 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 似乎不为空,但它也无法使用,因为它没有被分配。在这种情况下,控制台输出为:

错误

为什么(myObject == null) 是假的,而Debug.Log(testObject) 给我null 只要相应的对象没有在统一检查器中分配。

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

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

【问题讨论】:

    标签: c# unity3d isnull


    【解决方案1】:

    Unity 有一个自定义实现相等 == 运算符(请参阅 Custom == operator, should we keep it?,这通常会导致混淆/意外行为。

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

    特别是因为

    public GameObject testObject = null;
    

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


    GameObject 派生自的UnityEngine.Object 有一个隐式运算符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;
    }
    

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

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

    【讨论】:

    • 谢谢,很好。谢谢。有没有办法以一种也适用于所有 Not Unity Engine 对象的方式重载此方法,然后我可以以“经典”方式检查所有其他可空值是否为空?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多