检查是否在Unity3D

检查是否在Unity3D

本文介绍了检查是否在Unity3D 2019.3.05f的检查器中分配了GameObject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:

具体示例:

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

 公共静态布尔值IsNull< T>([CanBeNull]此T myObject,字符串消息="){如果(myObject!= null)返回false;Debug.LogError(对象为空!" +消息);返回true;} 

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

 公共类TestScript:MonoBehaviour{公共GameObject testObject = null;公共无效TestObject(){var result = testObject.IsNull(错误消息");Debug.Log(结果);Debug.Log(testObject);}} 

在大多数情况下,我的方法可以完美地工作,并在编码/调试期间节省了大量时间.但是我现在的问题是,如果我没有在编辑器中签署"testObject",我的测试将无法进行,因为testObject似乎不为null,但由于未分配,因此它也不可用.在这种情况下,控制台输出为:

(myObject == null)为何为假,而 Debug.Log(testObject)给我 null 只要相应的对象尚未在统一检查器中分配.

编辑/解决方案:多亏了derHugo的帮助,我最终得到了以下通用代码段:

 公共静态布尔值IsNull< T>(此T myObject,字符串消息="),其中T:class{开关(myObject){!obj时的大小写UnityEngine.Object obj:Debug.LogError(对象为空!" +消息);返回true;不区分大小写:Debug.LogError(对象为空!" +消息);返回true;默认:返回false;}} 
解决方案

Unity具有自定义的等价性实现 == 运算符(请参见自定义==运算符,我们应该保留它吗?这通常会导致混乱/意外行为.>

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

尤其是

  public GameObject testObject = null; 

是一个 public 字段,它会自动序列化,因此您分配给它的 null 值在序列化过程中仍将被覆盖./p>


UnityEngine.Object 其中 GameObject 派生自具有隐式运算符 bool

您应该检查

,而不是直接进行 == null 比较

 公共静态布尔值IsNull (此T myObject,字符串消息="),其中T:UnityEngine.Object{如果(!myObject){Debug.LogError("对象为null!" +消息);返回false;}返回true;} 


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

 公共静态布尔值IsNull< T>(此T myObject,字符串消息="),其中T:class{如果(myObject是UnityEngine.Object obj){如果(!obj){Debug.LogError("对象为null!" +消息);返回false;}}别的{如果(myObject == null){Debug.LogError("对象为null!" +消息);返回false;}}返回true;} 

Question:

Concrete Example:

I am about to write a generic method for Unity3D, that can be called on any nullable object. It checks if the object is null and if so it writes a Debug.LogError(customMessage). The Method looks like as follows:

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

The method can be called on any nullable object, anywhere in the code, for example within this simple Monobehaviour:

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

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

For most use cases my method works perfectly and saves a lot of time during encoding/debugging. But my problem now is that if I haven't signed the "testObject" in the editor, my test won't work because the testObject seems to be not null, but it's also not usable because it's not assigned. In this case, the console output is:

How comes that (myObject == null) is false, while the Debug.Log(testObject) gives me null as long as the corresponding object has not been asigned in the unity inspector.

Edit/Solution:Thanks to the help from derHugo I ended up with this generic code snippet:

 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;
        }
    }
解决方案

Unity has a custom implementation of equality == operator (see Custom == operator, should we keep it? which often leads to confusion / unexpected behavior.

Even if an UnityEngine.Object has a value equal to null it is sometimes not == null.Object rather still stores some meta data in it e.g. you get a MissingReferenceException, not a usual NullReferenceException because Unity implemented some custom exceptions that often hold more detail to why the value is equal to null.

Especially since

public GameObject testObject = null;

is a public field it is automatically serialized and thus the null value you assigned to it will be overwritten anyway during the serialization.


UnityEngine.Object which GameObject derives from has an implicit operator bool

Instead of a direct == null comparison you should rather check for

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


For a general method working for any reference type you could e.g. use something like

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

这篇关于检查是否在Unity3D 2019.3.05f的检查器中分配了GameObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 13:07