Что именно возвращает GetComponent?
GetComponent в Unity ведёт себя по‑разному для встроенных компонентов движка и ваших собственных MonoBehaviour. В Редакторе отсутствующие компоненты движка, вроде Renderer, могут возвращать особый «псевдо‑null» объект с переопределённым оператором ==, тогда как в Standalone это настоящий null; для ваших собственных типов в обоих случаях возвращается реальный null. В посте мы разбираем логи и объясняем, почему так (и чем отличается TryGetComponent), чтобы вы могли писать надёжные проверки на null в разных окружениях.
Jun 5, 2022
Привет, друзья Unity. Уверен, вы используете GetComponent<T>() каждый день. Но задумывались ли вы, что именно он возвращает? Давайте разбираться!
Представим ситуацию: у нас есть два класса, производных от MonoBehaviour: MyClassA и MyClassB. В сцене есть GameObject, и единственный скрипт, прикреплённый к этому GameObject, — это MyClassA — больше ничего, ни других компонентов, ни скриптов.
Теперь попытаемся вызвать GetComponent<MyClassB>() и GetComponent<Renderer>() из MonoBehaviour MyClassA. Это выглядит так:
using UnityEngine;
namespace GetComponentExample
{
public class MyClassA : MonoBehaviour
{
private void Start()
{
//Some class nested from MonoBehaviour
//Or HingeJoint, Or MeshFilter, etc.
var notExistingMonobehaviour = GetComponent<MyClassB>();
var notExistingRenderer = GetComponent<Renderer>();
Debug.LogWarning(notExistingMonobehaviour == null);
Debug.LogWarning((object)notExistingMonobehaviour == null);
Debug.LogWarning(notExistingRenderer == null);
Debug.LogWarning((object)notExistingRenderer == null);
TryGetComponent<MyClassB>(out var stillNotExistingMonobehaviour);
TryGetComponent<Renderer>(out var stillNotExistingRenderer);
Debug.LogWarning(stillNotExistingMonobehaviour == null);
Debug.LogWarning((object)stillNotExistingMonobehaviour == null);
Debug.LogWarning(stillNotExistingRenderer == null);
Debug.LogWarning((object)stillNotExistingRenderer == null);
}
}
}
Вопрос: что будет выведено в Debug.Log() в Редакторе и в Standalone‑сборке — и почему? Немного подумайте, пожалуйста. Если уже готовы с ответом, сверимся:
Лог в Редакторе: True, True, True, False, True, True, True, True
Лог Standalone‑сборки: True, True, True, True, True, True, True, True.
Лог Редактора:
Почему этот код возвращает True и в Редакторе, и в Standalone:
А этот — False в Редакторе и True в Standalone:
Дело в том, что результат вызова GetComponent<Renderer>() интересен: возвращается не обычный null, а «псевдо‑null» объект. У него переопределён оператор == для проверок на null. Unity Editor выделяет такой объект для компонентов Unity вроде Renderer, MeshFilter, HingeJoint и т. д.
Однако в Standalone такой «псевдо‑null» объект не выделяется.
В то же время GetComponent<MyClassB>() возвращает настоящий null и в Редакторе, и в Standalone‑сборке.
А что насчёт TryGetComponent? Этот метод ведёт себя иначе: он всегда присваивает своему out‑параметру реальный null и не создаёт «псевдо‑null». Поэтому, выбирая между GetComponent и TryGetComponent, учитывайте различия в возвращаемых результатах.

