GameObject в Unity C#: создание, поиск и управление объектами
GameObject в Unity — базовый класс для всех объектов, которые могут существовать в сцене: персонажи, декорации, источники света, камеры. Сам по себе GameObject пуст — это контейнер для компонентов, которые определяют, как объект выглядит и ведёт себя.
Устройство
- GameObject — это контейнер: компоненты вешаются на него через инспектор или
AddComponent. - Любой скрипт, наследующий
MonoBehaviour, можно добавить на GameObject как компонент. - Из собственного скрипта объект доступен через свойство
gameObject. - Событийные функции (Update и другие) вызываются, только если объект активен: одновременно верны
activeSelfиactiveInHierarchy.
Создание объекта из кода
Самый простой способ — конструктор. В примере из документации Unity создаётся пустой объект с компонентом AudioSource за один вызов:
using UnityEngine;
public class ObjectFactory : MonoBehaviour
{
void Start()
{
// Имя + типы компонентов через параметры конструктора
GameObject go = new GameObject("myExampleGO", typeof(AudioSource));
Debug.Log("Создан объект: " + go.name);
}
}
Но чаще объекты клонируют из префабов — там уже настроены компоненты, свойства и дочерние объекты. Подробно это разбирается в статье Instantiate в Unity C#.
Основные свойства
| Свойство | Что возвращает |
|---|---|
activeSelf |
Локальное состояние активности объекта (только чтение) |
activeInHierarchy |
Активен ли объект с учётом всех родителей (только чтение) |
tag |
Метка объекта — для поиска и группировки |
layer |
Номер слоя: физика, рендеринг, рейкасты |
isStatic |
Статический ли объект (флаги статичности) |
scene |
Сцена, в которой находится объект |
Разница между activeSelf и activeInHierarchy принципиальна: дочерний объект может быть «включён локально», но выключен вместе с родителем — тогда activeSelf равен true, а activeInHierarchy равен false.
Включение и выключение
using UnityEngine;
public class ToggleDemo : MonoBehaviour
{
public GameObject panel;
void Update()
{
if (Input.GetKeyDown(KeyCode.Tab) && panel != null)
{
// Переключатель: включает выключенное, выключает включённое
bool next = !panel.activeSelf;
panel.SetActive(next);
Debug.Log("Панель активна: " + next);
}
}
}
Учтите: при выключении объекта корутины, запущенные его компонентами, останавливаются (активность объекта, а не enabled компонента), а при повторном включении Awake не вызывается заново — он срабатывал при первой активации.
Поиск объектов
| Метод | Особенности |
|---|---|
GameObject.Find("Имя") |
Ищет по имени среди активных объектов. Медленный: перебор всей сцены |
GameObject.FindWithTag("Метка") |
Поиск по тегу, быстрее имени. Возвращает первый найденный |
GameObject.FindGameObjectsWithTag |
Все объекты с тегом |
FindAnyObjectByType |
Любой активный объект указанного типа (современный API Unity) |
FindObjectsByType |
Все объекты указанного типа |
Правило производительности: не ищите объекты в Update. Результат поиска кэшируйте в Awake или Start.
GameObject и Transform
На каждом GameObject есть хотя бы один компонент — Transform, отвечающий за позицию, вращение и масштаб. Поэтому transform доступен напрямую, без GetComponent, а доступ к родителю и детям идёт через него.
Частые ошибки
1. GameObject.Find каждый кадр
Полный перебор объектов сцены в Update — путь к просадке FPS. Кэшируйте при старте.
2. Путаница activeSelf и activeInHierarchy
Проверка panel.activeSelf вернёт true даже у объекта, чей родитель выключен. Для «видим ли объект сейчас» проверяйте activeInHierarchy.
3. Поиск выключенных объектов
Find и FindWithTag не видят неактивные объекты. Если цель может быть выключена — ищите через FindObjectsByType с включением неактивных или держите ссылку заранее.
4. Сравнение с настоящим null
Unity переопределяет оператор ==: уничтоженный через Destroy объект не равен C#-null, но равен null с точки зрения Unity. Сравнивайте с null напрямую — Unity-оператор обработает это корректно.