Теги, слои и поиск объектов
В большой сцене сотни объектов. Как герою понять, что он коснулся именно врага, а не стены? Помогают теги и слои.
Суть: Тег (Tag) — текстовая метка объекта ("Player", "Enemy", "Coin"), по которой его можно узнать. Слой (Layer) — группировка для физики и рендера: например слой "Ground" сталкивается с игроком, а слой "UI" — нет. Это разные механизмы для разных задач.
Когда герой во что-то врезается, скрипт должен решить: это враг (получить урон), монета (подобрать) или стена (просто остановиться)? Проверять имена объектов ненадёжно. Поэтому объекты помечают тегами — короткими ярлыками, и код спрашивает: if (other.CompareTag("Enemy")).
Слои решают другую задачу — кто с кем сталкивается и кто что видит. В матрице столкновений можно задать: пули игрока бьют врагов, но не самого игрока. Это настраивается на уровне слоёв, без единой строчки кода.
Как работает под капотом
Матрица столкновений по слоям:
Player Enemy Bullet Ground
Player - да нет да
Enemy да - да да
Bullet нет да - да
Ground да да да -
"да" = объекты этих слоёв сталкиваются друг с другом.
Так пуля игрока (слой Bullet) не бьёт самого Player.Тег и слой — независимы. У объекта может быть тег Enemy и слой Hostile одновременно. Тег чаще используют в коде для опознания, слой — для физики и рендера.
Смоделируем диспетчеризацию столкновения по тегу на Python:
# У героя есть здоровье и монеты. Реакция зависит от тега объекта
state = {"hp": 100, "coins": 0}
def on_collision(tag):
if tag == "Enemy":
state["hp"] -= 20
return "Ой! Получили урон"
elif tag == "Coin":
state["coins"] += 1
return "Подобрали монету"
elif tag == "Ground":
return "Стоим на земле"
return "Просто столкновение"
for tag in ["Coin", "Enemy", "Ground", "Coin"]:
print(on_collision(tag), "| hp:", state["hp"], "монеты:", state["coins"])Та же логика на Python ▶ — ровно так в Unity скрипт реагирует на столкновение: смотрит тег второго объекта и решает, что делать. Это сердце игрового взаимодействия.
Отдельная тема — как достать ссылку на другой объект. Есть два пути: перетащить объект в поле скрипта прямо в Inspector (быстро, надёжно) или найти его в коде через GameObject.FindWithTag("Player"). Первый способ предпочтительнее: он быстрее и не ломается при переименованиях.
Частые ошибки
- Сравнивать теги через ==. Сравнение
gameObject.tag == "Enemy"работает, ноCompareTag("Enemy")быстрее и безопаснее — используй его. - Опечатки в тегах.
"Enemy"и"enemy"— разные теги. Опечатка тихо ломает логику без ошибки. - Злоупотреблять Find в Update. Поиск объектов каждый кадр тормозит игру. Найди один раз в
Startи сохрани ссылку.
Best practices
- Связывай объекты через поля в Inspector везде, где можно — это быстрее любого Find.
- Настраивай матрицу слоёв (Edit → Project Settings → Physics 2D), чтобы лишние столкновения вообще не считались — это и логика, и оптимизация.
- Заведи понятный набор тегов и слоёв в начале проекта и держись его.
Итоги: теги — для опознания объектов в коде (CompareTag), слои — для управления столкновениями и рендером через матрицу. Ссылки на объекты лучше задавать через Inspector, а не искать каждый кадр. Не путай теги и слои: это разные инструменты для разных задач.
Слой ещё и для рендера и рейкастов
Мы говорили про слои в контексте физики, но у них есть и вторая жизнь. Камера может рисовать только определённые слои через свою маску Culling Mask — так, например, прячут отладочную графику в финальном билде, не удаляя её. Лучи-проверки (рейкасты), которыми игра спрашивает «что под курсором?» или «есть ли земля под ногами?», тоже умеют фильтровать по слоям: луч проверки земли игнорирует слой врагов и реагирует только на Ground. Это превращает слои в универсальный инструмент фильтрации «кого учитываем, кого нет» — в физике, в рендере, в логике. Поэтому продуманный набор слоёв в начале проекта окупается многократно, а хаотичное навешивание слоёв задним числом, наоборот, порождает трудноуловимые баги.