31 мая 2020 31.05.20 3 2730

Паркур и Unity3D. Создание собственной системы паркура. Часть 1

+2

Доброго времени суток. Представлюсь, для тех, кто меня еще не знает. Меня зовут Дима. Я работаю C++ разработчиком уже более 5 лет. На данный момент работаю в крупной Gamedev-студии. Помимо работы увлекаюсь созданием образовательного контента для YouTube и Twitch каналов. 

В своём небольшом пет-проекте я вдохновился идеей реализовать свою систему паркура. 

Что такое паркур? Паркур – скоростное перемещение и преодоление препятствий с использованием прыжковых элементов. Главная проблема, которую надо решить: персонаж должен уметь не только прыгать и бегать, но и взаимодействовать с препятствиями. Лучшим примером паркура в играх от 3-го лица можно назвать серию Assassin's Creed, а в играх от первого лица это бесспорно Mirror’s Edge. Последней я и буду вдохновляться. Разберу решение, к которому я пришёл на данный момент и какие задачи я при этом решил.

Пометка: данный пост является немного переделанной под местный формат моей же статьёй с сайта DTF. На Stopgame нет возможности в читаемой форме выкладывать программный код, поэтому будут прикреплены ссылки на pastebin.com

Что такое препятствие?

В первую очередь определимся, что мы будем воспринимать как препятствие, с которым может взаимодействовать игрок. После недолгих раздумий я остановился на параллелепипедах, вращения которых вокруг осей OX и OZ равно 0. То есть это параллелепипеды нижняя и верхняя грань которых строго параллельны поверхности «пола». Не стоит их воспринимать как набор абстрактных кубов, по которым будет лазать главный герой. Настраивая их масштабы, из них можно сделать платформу из Mario, плоский рекламный щит, трубы системы вентиляции и так далее.

Какая у нас цель?

На данный момент я остановился на самом простом – Персонаж должен вместо попытки запрыгнуть на препятствие, как в играх старой школы, попытаться на него залезть, что будет сопровождаться специальной анимацией. 

Разбиение препятствия на составляющие

У каждого препятствия я выделил 5 основных элементов: четыре стены и верхняя грань. Стены – это та часть, по которой мы будем карабкаться, верхняя грань – цель. Для того, чтобы разбить препятствие, мы обратимся к компоненту BoxCollider. Используя его размеры, а также масштаб самого объекта, его вращение и координаты вычислим 8 точек углов параллелепипеда в мировой системе координат. Перейдём к реализации метода. 
Реализация разбиения препятствий на стены

Разберём класс ParkourObstacle. Главная задача данного класса – хранить набор стен и верхнюю грань, а также уметь определять, к какой именно стене относится переданная ему точка. Рассмотрим реализацию, элементы вроде свойств и конструкторов я на данном этапе исключу, дабы не отвлекать от сути. Полный код будет предоставлен в конце статьи. 

Реализация класса ParkourObstacle

Управление

Все предварительные операции сделаны. Теперь можно реализовать поведение персонажа. Сложно назвать это управлением, скорее определение момента, когда нужно запускать паркур. Не буду акцентировать внимание на собственной реализации скрипта управления от первого лица. В нём есть недоработки и не думаю, что очередным FPS-контроллером можно кого-то удивить. Если Вас интересует его реализация, пишите в комментариях, напишу статью. Всю логику паркура я вынес в отдельный скрипт, не скажу, что он легко и просто подойдёт любому скрипту управления от первого лица. Тем не менее, с небольшими изменениями в нём и в своей логике управления, Вы можете брать его на вооружение.

В двух словах условия запуска паркура можно описать так:

  1. Есть препятствия доступные для попытки паркура
  2. Игрок не касается земли
  3. Нажата клавиша перемещения вперёд
  4. В данный момент игрок не «паркурит»
  5. Нажата клавиша прыжка

Думаю стоит пояснять только первое условие. Препятствия доступные для попытки будут определяться с помощью CapsuleCollider, который будет триггер-коллайдером. То есть будет только определять попадание и выход из него других коллайдеров с помощью функций OnTriggerEnter и OnTriggerExit:

Реализация добавления новых препятствий

Далее в кадре логики, проверив все эти условия и определив препятствия для паркура(Physics.Raycast из позиции персонажа, а не камеры, направленный вперёд), мы убеждаемся, что расстояние до верхней грани препятствия не превышает допустимый лимит (настраиваемый параметр), и после этого запускаем алгоритм залезания: 

Реализация проверки условий и запуска паркура

Карабканье

Процесс залезание на препятствие я разбил на три этапа:

  1. Переход от перемещения к паркуру
  2. Подъём вверх
  3. Небольшое перемещение вперед и возвращение управления персонажу.

Зачем нужен переход? В большинстве случаев точка начала залезания не будет совпадать с положением персонажа в пространстве, поэтому надо персонажа плавно переместить и повернуть лицом к стене. Скорость перемещения будет настраиваемым параметром. Далее следует подъём вверх и перемещение вперед. Данный код будет выполнятся в рамках одной Корутины.

Логика умещается в три метода:

  1. StartClimbing — Вычисление стартовых точек, отключение управления запуск карабканья, сохранение скорости персонажа до начала паркура
  2. Climbing — Корутина, выполняющая три этапа перемещения.
  3. StopClimbing — Возвращение управления персонажу, придача ему скорости до паркура.

За подробностями прошу в код: 
Реализация процесса залезания на препятствие

Заключение

Наш персонаж научился определять, что есть препятствие, разбивать его на составляющие элементы и залезать на них. В данный момент я работаю над механикой бега по стенам. Благодарю за внимание, пишите свои пожелания и вопросы в комментариях. За развитием событий следите на Youtube. Полная разработка, подробные объяснения и демонстрацию работы можно найти в данном видео: 

 

Ссылки на нас на других ресурсах:

Полный код класса


Лучшие комментарии

Ваше видео не работает, но за статью спасибо — однозначно (+) сюда и в карму.

Недавно пытался разобраться с UNITY3D, но были проблемы с установкой. Какой-то конфликт между UnityHub и основной прогой, не хотел открывать мой проект после перегрузки. В итоге снёс UNITY и поставил UE4.
Думаю проект был более старой версии.
Спасибо за комментарий. Видео исправил.
Читай также