Формы столкновений и слои

Чтобы объект мог с чем-то столкнуться, ему нужна форма столкновения — невидимый контур, по которому движок считает касания.

Суть: CollisionShape2D задаёт форму тела, а слои и маски решают, кто кого вообще замечает.

Картинка персонажа сама по себе не сталкивается ни с чем: для движка это просто пиксели. Чтобы возникла физика, к телу добавляют узел CollisionShape2D — он несёт форму: прямоугольник, круг, капсулу. Именно по этой форме движок проверяет столкновения. Форму обычно делают чуть проще силуэта картинки: простой прямоугольник или круг считается быстрее и ведёт себя предсказуемее, чем точный контур.

Player (CharacterBody2D)
 ├── Sprite2D            <- что видит игрок
 └── CollisionShape2D    <- что чувствует физика
        форма: капсула

Вторая важная идея — слои и маски коллизий. Их две стороны. Слой (layer) отвечает на вопрос «в каких группах я нахожусь». Маска (mask) — «какие группы я замечаю». Например, монетка лежит в слое «предметы», а персонаж имеет в маске «предметы» — значит, персонаж замечает монетки. А вот две монетки могут не замечать друг друга, если у них нет в маске своего же слоя. Так ты управляешь, кто с кем взаимодействует, без единой строчки кода.

Полезно понимать, почему так важно не лениться с настройкой слоёв. Когда объектов на сцене десятки, бесконтрольные столкновения превращаются в кашу: пули врага бьют других врагов, монеты сталкиваются между собой, эффекты цепляют что попало. Грамотно расставленные слои и маски наводят порядок — каждый объект замечает только то, что должен. Это не просто оптимизация, а инструмент дизайна: ты заранее решаешь, кто во вселенной твоей игры вообще способен встретиться, а кто проходит друг сквозь друга, как призраки.

Как работает под капотом

Каждый кадр физический движок берёт все формы и проверяет пары на пересечение. Чтобы не проверять заведомо ненужные пары (пуля врага против пули врага), он сначала смотрит на слои и маски: если маска одного объекта не включает слой другого, пара пропускается. Это и оптимизация, и инструмент игрового дизайна.

Смоделируем проверку «замечают ли друг друга» на Python через битовые слои.

PLAYER = 1   # слой 0
ITEM   = 2   # слой 1
ENEMY  = 4   # слой 2

def can_detect(my_mask, other_layer):
    return (my_mask & other_layer) != 0

# Игрок замечает предметы и врагов:
player_mask = ITEM | ENEMY
print("Игрок видит предмет?", can_detect(player_mask, ITEM))
print("Игрок видит врага? ", can_detect(player_mask, ENEMY))

# Предмет никого не замечает (маска = 0):
item_mask = 0
print("Предмет видит игрока?", can_detect(item_mask, PLAYER))

Та же логика на Python ▶. Слои и маски — это битовые наборы, а проверка «замечаю ли» — побитовое И. Godot делает ровно это, только с галочками в инспекторе вместо чисел.

Полезно потренировать глаз на подбор размера формы. Если контур столкновения заметно больше спрайта, игрок будет злиться: его как будто бьют по пустому месту. Если заметно меньше — наоборот, удары и стены будут проходить «сквозь» героя, что выглядит как баг. Поэтому форму подгоняют так, чтобы она ощущалась честной: для персонажа часто берут капсулу чуть уже силуэта, для пуль — маленький круг. Хорошая коллизия незаметна — игрок просто чувствует, что попадания и столкновения справедливы, и это ощущение во многом рождается из аккуратно подобранной формы.

Частые ошибки

Самая частая ошибка новичка — добавить тело, но забыть CollisionShape2D или оставить его форму пустой: тогда столкновений просто нет, объект проходит сквозь всё. Вторая — путать слой и маску: «я в слое X» и «я замечаю слой X» — разные галочки, и их легко перепутать местами. Третья — делать форму столкновения по точному контуру картинки: это медленнее и порождает залипания на углах; бери простую форму. Четвёртая — слишком большая форма, торчащая за спрайт: персонаж «цепляется» за стены раньше, чем касается их визуально.

Best practices

Каждому телу — свой CollisionShape2D с заданной формой. Предпочитай простые формы: прямоугольник, круг, капсула. Продумай слои и маски заранее: заведи понятные слои (игрок, враги, предметы, стены) и настрой, кто кого замечает. Держи форму чуть меньше или вровень со спрайтом, чтобы столкновения совпадали с тем, что видит игрок.

Итоги: CollisionShape2D задаёт форму, по которой считаются столкновения; без неё физики нет. Бери простые формы. Слои говорят, в каких группах ты находишься, маски — какие группы ты замечаешь; вместе они решают, кто с кем взаимодействует. Под капотом это битовые наборы и побитовое И.

Проверьте себя
1. Что произойдёт, если у тела нет CollisionShape2D (или форма пустая)?
AИгра вылетит
BТело не будет ни с чем сталкиваться и пройдёт сквозь объекты
CТело станет невидимым
DТело будет двигаться быстрее
2. В чём разница между слоем и маской коллизий?
AЭто одно и то же
BСлой — в каких группах я нахожусь, маска — какие группы я замечаю
CСлой для 2D, маска для 3D
DМаска отвечает за цвет объекта