Проверьте, был ли GameObject назначен в инспекторе в Unity3D 2019.3.05f - PullRequest
0 голосов
/ 12 февраля 2020

Вопрос:

Как проверить, был ли опубликован c gameObject объекта MonoBehaviour в инспекторе в Unity3D, в качестве сравнения для null (object==null) терпит неудачу.

Конкретный пример:

Я собираюсь написать обобщенный c метод для 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;
 }

Метод можно вызывать для любого объекта, допускающего обнуление, в любом месте кода, например, в рамках этого простого монобиха:

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

Почему (myObject == null) ложно, а Debug.Log(testObject) дает мне null до тех пор, пока соответствующий объект не был назначен в инспекторе единства.

Редактировать / Решение: Благодаря помощи derHu go я получил этот обобщенный c фрагмент кода:

 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 Ответ

1 голос
/ 12 февраля 2020

Даже если UnityEngine.Object имеет значение , равное null, оно иногда не == null. Object скорее все еще хранит некоторые метаданные в нем, например, вы получаете MissingReferenceException, а не обычный NullReferenceException, потому что в Unity реализованы некоторые пользовательские исключения, которые часто содержат больше деталей для , почему значение равно null.

Тем более, что

public GameObject testObject = null;

является полем public, оно автоматически сериализуется и, таким образом, значение null, назначенное ему, будет перезаписано в любом случае во время сериализации.

UnityEngine.Object, из которого GameObject происходит, имеет неявный оператор 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...