Объекты в Unity: GameObject, компоненты и UnityEngine.Object без путаницы
Код ищет GameObject, в Inspector нужно назначить компонент, а документация говорит об Object. Слова похожи, но обозначают разный уровень работы. Из-за этой путаницы новичок может искать объект по всей сцене, хотя ссылка уже доступна, или выключать весь персонаж вместо одного эффекта.
Разберём, что является объектом сцены, что хранится в компоненте и как безопасно выбирать действие: получить, создать, выключить или удалить.
ТОП-5 курсов обучения Unity:
GameObject — объект сцены
Игрок, камера, источник света и пустая точка появления могут быть GameObject. Их возможности определяются компонентами. У обычного объекта есть Transform; видимость, физика и собственная логика добавляются другими компонентами.
Названия в Hierarchy помогают человеку, но не задают поведение. Объект с именем Player не получает управление автоматически. Нужно добавить нужный скрипт и компоненты, затем связать их настройками.
Базовая модель описана в руководстве GameObject. Практически полезно воспринимать Inspector как список возможностей выбранного объекта.
Компонент — часть объекта
Transform хранит положение, поворот и масштаб. Sprite Renderer рисует спрайт. Rigidbody 2D участвует в двухмерной физике. Собственный MonoBehaviour-компонент хранит данные и методы игровой логики.
Ссылка на GameObject позволяет работать с объектом целиком: например, выключить его. Ссылка на конкретный компонент позволяет обращаться к нужной возможности. Если вам нужно изменить здоровье, поле типа Health выражает задачу точнее, чем произвольный GameObject с последующим поиском.
Это уменьшает число скрытых предположений. В Inspector сразу видно, какой компонент требуется, а в коде меньше повторных GetComponent.
Что означает UnityEngine.Object
UnityEngine.Object — базовый тип для многих сущностей движка, включая GameObject, Component и ресурсы. Материал и текстура относятся к объектам Unity, но не являются GameObject сцены.
Не путайте его с object в C#: это базовый тип языка. Если пространства имён создают неоднозначность имени Object, указывайте полное имя UnityEngine.Object. Такое уточнение полезнее случайного удаления using, который нужен для другой части файла.
У ссылок на объекты Unity есть особенность сравнения с null: уничтоженный объект может вести себя как отсутствующий при проверке через оператор Unity. Поэтому учитывайте тип ссылки и не переносите все правила обычных C#-объектов без проверки. Поведение объясняется в документации оператора сравнения.
Как получить нужный объект или компонент
Если цель известна заранее, используйте сериализованное поле и назначьте ссылку в Inspector. Если нужен компонент на том же объекте, используйте GetComponent или TryGetComponent. Поиск в родителях и детях решает другие варианты структуры.
Например, камера знает конкретного игрока — ей удобно хранить ссылку на его Transform. Монета проверяет объект, вошедший в триггер, — ей нужен компонент этого участника. Общий поиск по сцене здесь часто добавляет неопределённость.
Способы и ограничения подробно разобраны в статье о поиске объектов. Выбирайте поиск по тому, где должна находиться цель и кто владеет её ссылкой.
Родитель, дети и координаты
Hierarchy выражает связь объектов. У персонажа могут быть дочерние модель, точка оружия и визуальный эффект. Изменение Transform родителя влияет на положение детей, а локальные координаты описывают положение относительно родителя.
position относится к мировому положению, localPosition — к локальному. Если оружие должно оставаться у руки, задавайте его положение в соответствующей структуре. Если нужно поставить объект в конкретную точку уровня, проверьте мировые координаты.
Непредсказуемый масштаб часто появляется из-за масштаба родителя. Перед исправлением размеров дочернего объекта проверьте всю цепочку Transform.
Выключить объект или компонент
SetActive(false) выключает GameObject и влияет на его компоненты и дочернюю иерархию. Если нужно только спрятать изображение, иногда достаточно выключить Renderer. Если нужно остановить определённую логику — соответствующий MonoBehaviour.
У объекта различаются activeSelf и activeInHierarchy. Первое показывает его собственный флаг активности; второе учитывает родителей. Дочерний объект с activeSelf = true не будет активно работать, если его родитель выключен. Это описано в справочнике SetActive.
Для проверки создайте отдельный управляющий объект, а целью выберите другое изображение:
Добавьте скрипт на управляющий объект, назначьте Target и в Play вызовите Test → Toggle target из меню компонента. Управляющий объект должен оставаться активным, чтобы позднее он мог включить цель снова.
Создать экземпляр или сохранить prefab
Prefab — сохранённая конфигурация объекта. Instantiate создаёт экземпляр подготовленного объекта во время работы. Для врагов удобно хранить prefab с готовыми компонентами и передавать место появления.
Проверьте, что назначаете именно ожидаемый исходный объект, и не смешивайте его с уже живущим экземпляром сцены. Экземпляр после появления может иметь собственное состояние: здоровье, цель и позицию.
Варианты вызова и поведение создания описаны в документации Instantiate. Для первой проверки создавайте один объект, прежде чем запускать волны из сотен экземпляров.
Уничтожение и повторное использование
Destroy удаляет объект или компонент. В обычном игровом коде фактическое удаление происходит не обязательно в точке вызова, поэтому сразу остановите повторную обработку события, если она могла прийти снова. Например, монета после подбора сначала выставляет флаг collected.
Для часто создаваемых объектов позже можно использовать пул: экземпляр временно выключают и возвращают в набор. Но возврат требует сбросить состояние. Выключенный враг с нулевым здоровьем не становится новым здоровым врагом только от SetActive(true).
Первый пример подбора и удаления объекта есть в игре с монетами.
Как выбрать правильное действие
Перед строкой кода уточните цель. «Спрятать эффект» может означать выключить Renderer. «Убрать сущность из мира» — удалить объект или вернуть его в пул. «Перестать принимать управление» — изменить состояние контроллера, оставив персонажа видимым.
Когда действие связано с нужным уровнем структуры, код становится легче читать. Вы понимаете, меняете ли данные компонента, активность GameObject или время жизни всей сущности.