Ходьба сквозь юнитов в Godot
Моя игра будет хоть и с видом сверху, но не совсем сверху - персонажи будут отображаться боком. Хз как это называется (точно не изометрия), но как в вампирах, в общем
Соответственно, задача - дать возможность юнитам заходить за других юнитов
Перед тем как разъясню решение, немного базы
Про коллизии
В Godot есть встроенная физика. Мне ещё предстоит протестить её возможности в полной мере, но базовые вещи в ней работают и пока этого достаточно
- Создаём ноду KinematicBody2D, назовём её Unit
- Кладём в неё ноду CollisionBody2D и рисуем какую хотим коллизию
- Теперь открываем настройки KinematicBody2D и в коллизии у нас есть две непонятные херни с цифрами
Из доки было непонятно, что это и как оно работает, но суть такова.
- Layer - это то, в каком слое находится наш объект
- Mask - это слои, с которыми наш объект будет сталкиваться
Если два объекта не сходятся (Layer одного не находится в Mask другого), то они друг друга игнорируют
Дабы не забыть, какая цифра за какой слой отвечает, можно сходить в Project -> Project Settings -> Layer Names -> 2D Physics и прописать цифрам названия. Цифрами они отображаться, к сожалению, не перестанут, но зато при наведении будет видно, что это
Движение
После создания коллизий, можем двигать юнита, навесив на него простой скрипт:
class_name SomeUnit extends KinematicBody2D var speed = 400 var direction = Vector2.LEFT var velocity = Vector2.ZERO func _physics_process(delta): velocity = speed * direction move_and_slide(velocity)
Так юнит будет двигаться в направлении direction
со скоростью speed
Для движения есть разные методы.
Например, move_and_slide
автоматически сдвинет юнита за пределы чужого коллайдера, если он окажется в нём. Ну например, мы делаем дэш, который отключает юниту коллизию, и он заканчивается до того, как мы "выйдем" из юнита. Эта штука автоматом его вытащит.
move_and_collide
, соответственно, упрёт юнита в препятствие и не будет пропускать сквозь.
Есть и ещё. Перечислять всё не буду, подробнее можно почитать тут: тык
Разумеется, прописывать каждому движущемуся юниту всё это каждый раз такое, поэтому я запилил дефолтный класс.
Делаем юнитов
В рамках своих хотелок сделал пока что 4 слоя: Environment, Body, Hitbox, Hit
- Один кружком в нижней части юнита. Это типа точка, где юнит "стоит". Его нужно будет обходить. Это будет Layer Body + Mask Environment, Body
- А второй будет размером с модельку. Он будет отвечать за получение урона. Это будет Layer Hitbox + Mask Hit
Кружок навесил на сам KinematicBody2D, чтобы логика ходьбы считалась от кружка. А второй коллайдер вложил внутрь в Area2D и назвал её CollisionHitbox
Всё, конечно, работает, но всплыл ещё один нюанс. Раз они друг за другом проходят, то надо же и правильно их отображать - кто ближе кого к камере, то есть какой спрайт отображать поверх какого
Подумал, что щас будет куча геморра с тем, чтобы трекать координаты каждого персонажа и поднимать спрайты одного выше другого, ведь у меня же тут не 3D...
Оказывается, всё гораздо проще, и в движке это уже реализовано по дефолту.
Есть специальная нода YSort. Нужно всего лишь положить юнитов в неё, и они автоматически отсортируются. Кайф
Не думаю, что это специфичная фича для Godot, в других движках наверняка тоже есть, уж больно критичная фича