В прошлой статье было небольшое введение в принцип работы Bolt и основы визуального программирования. В этой же попробуем небольшой платформер сделать и затронем основные аспекты.
Поработаем с силами, рейкастами и затронем тему модульности и переиспользования компонентов.
![](https://suvitruf.ru/wp-content/uploads/2021/03/unity-bolt-tutorials-2-1024x463.png)
Цикл статей
- Введение
- Платформер — движение, анимация, рейкасты
Туториалы можно скачать бесплатно с Гитхаба. Каждый туториал будет отдельной папкой в проекте. Конкретно этот туториал будет лежать в директории Assets/Tutorials/02 — Platformer.
Оглавление
Подготовка
Накидаем простенькую сцену с платформами и шипами. Я использовал редактор Тайлов, но это могут быть и обычные спрайты с колайдерами на них. Добавляем в иерархию GameObject
игрока.
![](https://suvitruf.ru/wp-content/uploads/2021/03/player_gameobject.png)
В инспекторе добавляем к объекту компонент Flow Machine.
![](https://suvitruf.ru/wp-content/uploads/2021/03/inspector_player_flowmachine.png)
Нажимаем Edit Graph и приступает к настройке графа.
Движение персонажа
Мы хотим, чтобы персонаж двигался влево и вправо в зависимости от горизонтальной оси ввода, для которой предварительно настроены сочетания клавиш A и D на клавиатуре или левый джойстик на контроллере. Когда вы идёте влево, возвращается -1
, а когда вправо, то +1
. Скорость движения зададим в переменной.
Для начала можно зайти в настройки и задать необходимое управление в Edit > Project Settings > Input Manager, если не нравятся дефолтные настройки.
![](https://suvitruf.ru/wp-content/uploads/2021/03/input_manager.png)
Теперь добавим переменную, откуда будем читать скорость. В инспектора объекта игрока добавим переменную в компоненте Veriables. Подробнее можно почитать в документации.
![](https://suvitruf.ru/wp-content/uploads/2021/03/add_speed_variable.gif)
Далее, собственно, нам нужно получить горизонтальную ось ввода. Мы можем сделать это с помощью блока Get Axis.
- Добавляем узел Codebase > Unity Engine > Input > Get Axis.
- Вводим «Horizontal» (зарезервированное слово).
Новый узел будет полупрозрачным. Так Unity нам сообщает, что они пока нигде не используется. Этот эффект можно отключить на панели отжав пункт Dim.
![](https://suvitruf.ru/wp-content/uploads/2021/03/get-axis.png)
Далее мы хотим на основании инпута вычислить итоговое значение скорости. Для этого нужно считать значение переменной Speed, созданной ранее, перемножить со значением с инпута и записать в новую переменную.
- От выхода узла GetAxis тащим указатель и создаём узел Multiply.
- От второго входа нового узла тянем указатель и создаём узел для чтения переменной Variables > Object > Get Object Variable.
- Выбираем там Speed.
- Выход узла Multiply соединяем с новым узлом Variables > Graph -> Set Graph Variable.
- Дадим новой переменной имя Movement.
- Соединяем управляющий вход с Update.
![](https://suvitruf.ru/wp-content/uploads/2021/03/set-movement-variable.gif)
Каждый кадр (событие Update) мы получаем значение инпута по оси X в диапозоне [-1;1], домножаем на скорость и сохраняем в переменную Movement.
Теперь нужно задать компоненту Rigidbody 2D персонажа скорость. Скорость состоит из двух составляющих — по осям X и Y, которые пакуются в Vector2
.
- Добавляем узел Get Variable для получения Movement из предыдущего шага.
- Это передаёт на вход X координате новой ноде Vector2.
- А в Y передаём считанную Y координату из текущей скорости (Codebase > Unity Engine > Rigidbody 2D -> Get Velocity).
- Полученный вектор передаём на вход узлу для установки нового значения скорости (Codebase > Unity Engine > Rigidbody 2D -> Set Velocity).
![](https://suvitruf.ru/wp-content/uploads/2021/03/set-velocity.gif)
Остаётся теперь связать выход узла по установке Movement со входом узла, устанавливающего скорость.
Ну и заодно сгруппируем узлы. Это делается выделением с зажатой клавишей Ctrl.
![](https://suvitruf.ru/wp-content/uploads/2021/03/calc-movement-and-set-horizontal-velocity.gif)
Если запустить редактор, можно увидеть, как персонаж двигает при нажатии на клавиши. Обратите внимание на граф и то, как меняется значение скорости на нём в режиме реального времени.
![](https://suvitruf.ru/wp-content/uploads/2021/03/movement_in_action.gif)
Даже при движении влево спрайт всё равно смотрит вправо. Хорошо бы это исправить. Для этого будет инвертировать значение скейла по оси X.
- Если двигаемся вправо (значение Movement больше 0), значение Scale должно быть положительным.
- Если движемся влево (значение Movement меньше 0), значение Scale должно быть отрицательным.
- Если стоим на месте (значение Movement равно 0), то ничего не делаем.
Значение Y и Z оставляем как есть.
![](https://suvitruf.ru/wp-content/uploads/2021/03/player-rotation.png)
Если запустить редактор, то увидим, что спрайт персонажа отзеркаливается в зависимости от направления движения.
![](https://suvitruf.ru/wp-content/uploads/2021/03/player-rotation.gif)
Но сейчас персонаж просто скользит. Хотелось бы сделать анимацию движения.
Анимация
Возьмём готовые спрайты и анимации из примера проекта Penny Pixel.
Если открыть аниматор, то нас там пока интересует всего 2 анимации: айдловая и бега. Если посмотреть на переход для анимации бега, то заметим, что оно зависит от скорости по оси X. Нам всего лишь нужно это значение передавать аниматору.
Ну и флажок grounded пока в true выставим, чтобы не запускалась анимация полёта.
![](https://suvitruf.ru/wp-content/uploads/2021/03/mecanim.png)
На графе, как я уже сказал, нам нужно всего лишь передать значение скорости аниматору и записать в переменную velocityX.
![](https://suvitruf.ru/wp-content/uploads/2021/03/animator-velocity-x.png)
Остаётся только соединить с остальным графом и запустить.
![](https://suvitruf.ru/wp-content/uploads/2021/03/player-animation-velocity-x.gif)
Следующим шагом добавим возможность прыгать.
Придание силы объекту для прыжка
- Добавим глобальную переменную для силы прыжка и назовём JumpPower.
- Events > Input, а там On Button Input.
- Вместе со считанной силой прыжка передаём в Codebase > Unity Engine > Rigidbody 2D > Add Force (Force, Mode).
![](https://suvitruf.ru/wp-content/uploads/2021/03/jump.png)
Если запустить, то по нажатию на Space персонаж будет прыгать. Но есть одна проблема…
![](https://suvitruf.ru/wp-content/uploads/2021/03/jump.gif)
Во-первых, нету анимации прыжка. Во-вторых, если, находясь в воздухе, снова нажать Space, то персонаж прыгнет ещё раз. А нам бы этого не хотелось.
Создадим новый слой и назначим его платформам.
![](https://suvitruf.ru/wp-content/uploads/2021/03/platforms_layer.png)
Необходимо дописать логику по проверке, находится ли персонаж на земле. Один из способов — рейкасты. Будем выпускать лучи вниз на небольшое расстояние, чтобы проверить, сталкиваются ли они с платформой. Проверять как раз по этому слою будем.
Переиспользование логики
Так как эта проверку нужна в двух местах, то выделим всю логику в отдельный юнит Assets > Create > Bolt > Flow Macro.
Для каста использовать будем CircleCast
. Хотя это не так принципиально.
- Получаем позицию текущую.
- Делаем рейкаст по слою Platform, направляя вниз с радиусом 2 и дальностью 2.
- Результат получаем в отдельную ноду.
- Делаем проверку на то, было ли столкновение.
- Результат проверки столкновения луча с платформой пишем в bool переменную IsGrounded на выход.
![](https://suvitruf.ru/wp-content/uploads/2021/03/flow_graph_fround_check-1024x375.png)
Теперь в графе персонажа нужно немного изменить узлы, обрабатывающие прыжок.
- Перетаскиваем на граф персонажа граф GroundCheck.
- Добавляем ветвление.
- Соединяем с узлом, задающим силу.
![](https://suvitruf.ru/wp-content/uploads/2021/03/ground_check_and_jump.gif)
Если запустить, то увидим, что персонаж теперь может прыгать только находясь на платформе.
![](https://suvitruf.ru/wp-content/uploads/2021/03/ground_check_is_grounded.gif)
Точно также добавим проверку к анимации.
![](https://suvitruf.ru/wp-content/uploads/2021/03/ground_check_animation.png)
Теперь, если персонаж в воздухе, будет проигрываться соответствующая анимация.
![](https://suvitruf.ru/wp-content/uploads/2021/03/complete_animation_and_ground_check.gif)
Хотелось бы как-то визуализировать дебажную информацию для отладки.
Отладка и OnDrawGizmos
Было бы неплохо как-то визуализировать рейкаст. Как минимум, хочется видеть, как далеко он бьёт. Для этого можно воспользоваться событием OnDrawGizmos
, которое позволяет в редакторе рисовать отладочную информацию.
В нашем случае просто будет рисовать линию. Увеличим дальность луча до 50 и добавим соответствующие узлы для отрисовки линии.
![](https://suvitruf.ru/wp-content/uploads/2021/03/OnDrawGizmos-1024x487.png)
- Вытаскиваем информацию о текущем положении.
- Создаём Vecto3 на основе X и Z координаты. Эта позиция будет конечной при отрисовки линии.
- Рейкаст мы делаем вниз, поэтому в Y координату вписываем Y координату текущего положения персонажа с за вычетом дальности луча.
- Добавляем ивент, который каждый кадр рисует информацию.
- На вход узла по отрисовке в начальную координату передаём текущее положение персонажа, а конечной точкой будет новое вычисленное значение позиции.
Ещё нужно в Scene View включить отображение Gizmos.
![](https://suvitruf.ru/wp-content/uploads/2021/03/enable_gizmos.png)
Теперь запустим и посмотрим.
![](https://suvitruf.ru/wp-content/uploads/2021/03/ground_check_and_gizmos.gif)
Увеличив дальность проверки для рейкаста мы дали возможно персонажу прыгать даже в воздухе.
В следующей статье поработаем с окнами и сделаем экран смерти персонажа с перезапуском сцены.
Если хотите поддержать выход статей, сделать это можно одним из способов.