2d контроллер движения персонажа в unity
Основы создания 2D персонажа в Unity 3D 4.3. Часть 2: бегущий персонаж
Всем привет. Продолжаем дело, начатое в первой части. Сейчас у нас есть платформа и стоящий на ней персонаж с анимацией покоя. Настало время научить нашего персонажа бегать вправо-влево по платформе.
Загрузим сцену из первой части. Напомню, что в прошлый раз мы импортировали несколько спрайтов в папку Assets — Sprites. На всякий случай, внизу поста еще раз приведу ссылку на спрайты. Среди них должен быть спрайт под названием Run. Мы будем использовать его для создания анимации бега. Для этого нам надо проделать те же действия по превращению одиночного спрайта в коллекцию, как и при создании анимации покоя. Вкратце напомню: выделяем спрайт, в окне Inspector устанавливаем свойство Sprite Mode как Multiple, нажимаем ниже Sprite Editor, нарезаем изображение в режиме Grid или Automatic.
Теперь в окне Hierarchy выбираем Character и переходим в окно Animation. Нажимаем на поле с анимацией Idle и выбираем Create New Clip, чтобы создать анимацию бега. Сохраним файл анимации в папке Assets — Animations под именем Run.
Новая созданная анимация Run стала текущей в окне Animation. Разворачиваем спрайт Run в окне Project, выделяем все фалы Run_0… Run_9 и перетаскиваем в окно Animation. Установим пока значение Sample равное 24.
Все это мы уже делали в первой части, а теперь будет нечто новое. Перейдем в окно Animator. Сейчас там отображены три анимации: Any State, Idle и Run. Нам предстоит задать условия перехода из анимации Idle в анимацию Run, то есть из состояния покоя в состояние бега. В нижнем левом углу есть поле Parameters. Нажимаем на плюсик, выбираем Float и называем новый параметр как Speed. Тем самым мы создали параметр типа число с плавающей запятой, обозначающий скорость перемещения персонажа. Именно в зависимости от значения этого параметра будет происходить переключение из анимации покоя в анимацию бега. Теперь нажимаем правой кнопкой мыши на анимацию Idle, выбираем Make Transition и нажимаем левой кнопкой мыши на анимацию Run. Между анимациями появится линия со стрелкой. Передвиньте мышкой прямоугольники анимации, если плохо видно. Кликнем по линии со стрелкой. В окне Inspector отобразятся свойства перехода между анимациями. Обратим внимание на низ окна, в раздел Conditions. Кликнем на параметр Exit Time и поменяем его на Speed. Второе поле Greater оставим без изменений, а в третьем введем значение 0.01. Мы создали условие перехода из анимации покоя в анимацию бега — оно происходит, когда значение параметра скорости становится немногим больше нуля.
Теперь нужно сделать обратный переход — из Run в Idle. Делаем все с точностью наоборот: Make Transition от Run к Idle, выделяем переход, в Conditions устанавливаем Speed — Less — 0.01.
Теперь у нас есть две анимации и условия перехода между ними. Но пока ничего работать не будет, потому что все что мы сделали нужно «оживить» при помощи скрипта. Давайте перейдем в окно Project и создадим в папке Assets подпапку Scripts. Добавим в нее новый C# Script, назовем его CharacterControllerScript и откроем на редактирование.
Я приведу полный листинг скрипта с подробными комментариями, а ниже еще поясню, что в нем происходит.
Итак, мы завели несколько переменных: для задания максимальной скорости перемещения, для определения направления (вправо/влево) и для работы с компонентом Animator. Почти все действия происходят в методе FixedUpdate. В нем мы получаем значение оси Х, которое меняется при нажатии на клавиатуре клавиш влево-вправо или A-D (если не меняли соответствующие настройки проекта!). Затем устанавливаем это значение параметру Speed компонента Animator. Обратите внимание, что мы берем модуль этого значения при помощи метода Mathf.Abs, так как при создании условий перехода между анимациями покоя и бега мы сравниваем значение параметра с положительным числом 0.01. Нам здесь не важно, в какую сторону бежит персонаж. Важно лишь величина значения. Далее задаем скорость перемещения по оси Х в соответствии со значением максимальной скорости. И, наконец, проверяем, в какую сторону бежит персонаж, и в какую сторону он в этот момент повернут. Если он бежит вправо, а повернут влево — разворачиваем его вправо путем инвертирования его размера по оси Х. И наоборот. Этим нехитрым способом мы избавились от необходимости делать две анимации вместо одной: для бега вправо и для бега влево.
Сохраняем скрипт. В Unity перетаскиваем его на нашего Character в окне Hierarchy. Запускаем игру, нажимаем влево-вправо или A-D.
Капитан Коготь теперь умеет бегать! Скорость анимации получилась быстроватой. Ее можно снизить путем уменьшения значения Sample в окне Animation для анимации Run (значение 12 будет нормально). Если одновременно с игрой у вас видно окно Animator, то вы увидите, что во время покоя работает анимация Idle (бегает синий прогрессбар), а во время бега происходит переход на анимацию Run, и, соответственно, работает она.
На этом пока все. Нам осталось разобраться с прыжками… и узнать при этом еще несколько новых вещей!
Ссылка на спрайты.
Как работает Unity Character Controller (Контроллер Персонажа)?
Команда Unity3D заботится о рядовых пользователях и разработчиках игр. Поэтому в Unity была введена интересная система, называется она – Character Controller, а по русски – Контроллер Персонажа. Что же она делает и для чего вообще нужна? В основном она используется для управления персонажем от первого или третьего лица без использования физики Rigidbody.
Итак для начала нам следует подготовить сцену. Создадим Terrain, Меню GameObject>3d Object>Terrain
И создадим заготовку нашего персонажа. Для этого опять, Меню GameObject>Create Empty и назовем его Player. Затем делаем нашу камеру дочерней нашему свежесозданному Player.
Теперь добавим плееру компонент Character Controller. Для этого в окне инспектора нажмем кнопку Add Component и в появившемся списке в пункте Physics нажмем на Character Controller.
Когда контроллер персонажа добавлен к нашей заготовке, рассмотрим подробнее поля его настроек.
Slope Limit: этот параметр ограничивает возможность персонажу взбираться на различные препятствия. Например, по умолчанию стоит число 45, это значит, что если угол препятствия больше 45 градусов, то персонаж на него не сможет взобраться.
Step Offset: персонаж будет подниматься по лестнице, только если он ближе к земле, чем указанное значение.
Skin width: 2 коллайдера могут пересечься друг с другом на глубину, равную значению Skin Width.
Min Move Distance: если персонаж пытается переместиться ниже указанного значения, он не будет двигаться вообще.
Center: сдвиг коллайдера контроллера.
Radius: радиус коллайдера контроллера. Определяет, насколько жирный получился персонаж.
Height: высота коллайдера. Ну и, соответственно, высота контроллера. Например, если сделать это значение выше высоты дверных проемов, то персонаж просто застрянет в них.
Пока все значения оставим по умолчанию. В дальнейшем можно поменять их для лучшей работы контроллера. И как, это не странно, подготовка персонажа готова. Нам осталось написать небольшой скрипт управления камерой и нашим контроллером и персонаж будет готов.
Создадим новый скрипт под названием Player. Этот скрипт нам нужен для отдачи команд CharacterController, который и будет их выполнять, двигая и поворачивая персонажа. Для этого выберем в иерархии нашего персонажа и в инспекторе нажмем Add Component. Далее, в конце появившегося списка, нажимаем New Script, в появившемся поле ввода вводим название скрипта, в нашем случае – Player.
Завершающие действие – это кнопка Create and Add. Нажимаем! Отлично, скрипт создан и добавлен к нашему персонажу!
Откроем его, кликнув по его имени два раза.
В этом скрипте нам надо обьявить три переменные. Первая – это ссылка на CharaсterController. Вторая – скорость движения. Третья-скорость поворота. И укажем им значения по умолчанию 1 и 3 соответственно.
В методе Start, который, как мы знаем, вызывается при старте сцены, добавим строку, которая найдет и добавит компонент CharacterController к нашей переменной. Конечно же, при условии, что он присутствует на том же GameObject что и наш скрипт.
Теперь переходим к методу Update. Этот метод вызывается каждый кадр. В него для начала добавим строку, которая поворачивает наш персонаж вокруг оси Y, посредством клавиш leftArrow и RightArrow.
Затем мы задаем, куда нам двигаться. Точнее – вектор направления. Он у нас forward или z.
Затем мы устанавливаем скорость движения. В зависимости от того, какая клавиша нажата, она положительная или отрицательная. То есть вперед и назад.
И наконец, собираем все это вместе и передаем на Character Controller.
Сохраняем наш скрипт и переходим в Unity. На нашем персонаже должно быть два скрипта Charaster Controller и Player.
Жмем Play и стрелочками на клавиатуре двигаем и поворачиваем нашего персонажа. Урааа, побежали!
Продолжаем делать наш Unity for dummies платформер.
Полные версии кода будут находиться в конце поста.
Если вы не в курсе, как работают хуки жизненного цикла в Unity, вы можете ознакомиться с данной статьёй.
Создаём в панели ассетов C# cкрипт PlayerBehaviour, и запихиваем его в папку Scripts (её можно создать в той же панели ассетов).
Затем выбираем наш объект Player слева, в меню иерархии, и закрепляем инспектор (меню справа), нажав на замок в верхнем правом углу.
Пока закрываем все ненужные компоненты (Box Collider 2D, etc), нажимая на стрелочку у каждого из них.
Теперь перетаскиваем наш скрипт в инспектор, и он прикрепляется к объекту Player (если вы не выполнили предыдщуий пункт с закрепением меню, то вы этого сделать не сможете).
Если зайти в Edit => Project Settings => Input Manager, то мы можём увидеть настройки управления. Например, прыжок (Jump) назначен на пробел, в то время, как движение по горизонтали назначено на a, d, ←,→.
Запомним это для того, чтобы затем использовать в коде (названия инпутов Jump, Horizontal).
Пора покодить. Два раза нажимаем на наш скрипт PlayerBehaviour, и Unity отдаст его в руки Visual Studio.
Сохраняем файл, и переходим обратно в Unity. После того, как Unity проверит код (линтинг, ошибки, пустые переменные). Если что то неправильно, то вы увидите сообщение об ошибке.
Исправляем код, и страшные красные буквы исчезают. Можно запустить игру, и проверить, как все работает.
Мне не нравится, что персонажа переворачивает. Исправим.
Заходим в инспектор, открываем Rigidbody2D и ставим галочку на Freeze Rotation Z.
Есть два основных способа научить камеру двигаться за персонажем.
1. Подвинуть камеру внутри сцены, чтобы она была на персонаже, а затем в привязать камеру к объекту персонажа через меню иерархии.
2. Задать движение камеры за персонажем програмно.
Создаём скрипт CameraBehaviour, и привязываем его к объекту Main Camera (добавляем через инспектор).
Открываем наш новый скрипт, и начинаем кодить (да, мне на работе не хватает, продолжаю и после).
Фиксируем объект камеры на замок в инспекторе, и перетаскиваем наш объект Player в GameObject.
Теперь камера двигается за игроком.
Однако камера постоянно вылезает за пределы уровня, показывая синий фон.
Я не уверен, что моё решение правильное. Буду рад, если кто-нибудь поделится своими соображениями на данный счёт.
Добавляем в наш скрипт CameraBehaviour следующий код:
Двигаем камеру, и снимаем наши измерения ее положений.
На скрине ниже камера стоит в левом нижнем углу сцены.
Проставляем снятые позиции для камеры (мои и ваши позиции будут отличаться).
Теперь обновим метод UpdateCameraPosition в скрипте CameraBehaviour
Отлично, камера перестала «гулять». Работаем дальше.
Выбираем наш Foreground, и создаём новый слой ‘Ground’ в инспекторе.
Снова тыкаем на Foreground, и выбираем в поле Layer наш только что созданный слой.
Добавим в PlayerBehaviour такую строчку.
Теперь в объекте Player мы можем выбрать наш свежесозданный слой.
Обновляем наш PlayerBehaviour. Добавим коллайдер (rigidBody мы создавали ранее).
Теперь мы можем обновить обработку перемещения персонажа в методе updatePlayerPosition
Летать мы разучились, а по платформе больше не скользим. Победа!
Я не уверен, что моё решение правильное. Буду рад, если кто-нибудь поделится своими соображениями на данный счёт
Привет.
Я, конечно, дохуя вовремя, когда у тебя уже пять статей и рефакторинг, но вот щас иду за тобой пока вот на этом месте.
Короче, в ассет-сторе есть проект 2D Game Kit от разрабов движка. Там движение камеры сделано буквально следующим образом, если помню (давно открывал). Уровень завёрнут в коллайдер, ещё один коллайдер на камере. Соответственно, когда она о него стукается, то расслабляется и не двигается. И ещё там угарный камера-лаг стоит, чтоб камера не жёстко следовала за персонажем, а как бы за верёвочку.
Привет.
Да, я изначально так и пробовал.
Но персонаж, почему-то, попросту исчезает при старте игры.
Попробую ради эксперимента новый проект создать.
Character Controller
Свойства
Свойство: | Функция: |
---|---|
Slope Limit | Ограничивает возможность коллайдер взбираться по склонам только по склонам равным или меньше чем указанное значение. |
Step Offset | Персонаж переступит на поверхность, только если она ближе к земле, чем заданное значение. |
Skin width | 2 коллайдера могут пересечься друг с другом на глубину, равную значению Skin Width. Большее значение уменьшит степень тряски. Слишком низкое значение может вызвать застревание персонажа. Наилучшим вариантом является установление этого значения равным 10% от радиуса. |
Min Move Distance | Если персонаж попробует сдвинуться ниже указанной величины, то он не сдвинется. Это может быть использовано, чтобы уменьшить тряску. В большинстве ситуаций это значение стоит оставить равным нулю(0). |
Center | Сдвиг коллайдера в мировом пространстве без влияния на то, как вращается персонаж. |
Radius | Значение радиуса коллайдера. По сути дела, это ширина коллайдера. |
Height | Высота коллайдера Capsule Collider персонажа. Изменение её растянет коллайдер вдоль оси X в оба направления. |
Компонент Character Controller
Детали
Controller не реагирует на силы сам по себе и не отталкивает Rigidbody объекты автоматически.
С другой стороны, если вы хотите, чтобы персонаж игрока подвергался влиянию физику, то возможно вам было бы лучше использовать Rigidbody вместо Character Controller.
Настройка персонажа до желаемого результата
Вы можете менять значения Height и Radius для соответствия коллайдера мешу персонажа. Для человекоподобных персонажей рекомендуется использовать высоту около 2-х метров. Вы также можете изменить центр ( Center ) капсулы в случае, если точка вращения (pivot) не соответствует точному центру персонажа.
Значение Step Offset тоже важно при настройке, убедитесь, что это значение находится в диапазоне между 0.1 и 0.4 для 2-х метровых гуманоидов.
Slope Limit тоже должен быть не слишком маленьким. Зачастую использование значения в 90 градусов подходит лучше всего. Character Controller не сможет ползать по стена в виду формы капсулы.
Как не застрять
Skin Width одно из самых критических свойств для верной настройки Character Controller. Если вам персонаж застрял, то скорее всего ваше значение Skin Width слишком мало. Skin Width позволяет объектам слегка пересекать Controller, но уменьшает тряску и защищает от застревания.
Достаточно неплохой практикой является сохранение значения Skin Width как минимум больше чем 0.01 и и больше чем 10% радиуса коллайдера ( Radius ).
Мы рекомендуем оставлять значение Min Move Distance равным 0.
См. справку по скриптингу Character Controller здесь
Вы можете скачать проект-пример, демонстрирующий предустановленных анимированных и движущихся Character Controller’ов, с нашего вебсайта здесь Resources
Система управления в 2D платформерах
Конечно, когда мы говорим о жанре платформер, тем более в 2D играх, то система управления здесь реализуется на порядок проще, чем в более крупных 3D играх, к тому же, Unity предлагает множество уже готовых решений и все, что вам требуется – только правильно их использовать.
Если на ПК управление в большей части реализуется за счет мыши и клавиатуры, то с сенсорными экранами все немножко сложнее. На экране не расположишь все кнопки, поэтому приходится прибегать к дополнительным системам отлавливания действий игрока и управления персонажем.
В этой статье попробуем рассмотреть один из примеров такой системы управления.
И так, начнем с небольшой программной части, а именно – с событийной части взаимодействия игрока и персонажа через команды.
Система команд
Создаем скрипт с перечислениями ActionType в котором будут находится команды.
Добавим в этот скрипт метод, через который будут поступать команды персонажу.
Дальше создадим персонажа на сцене.
Дальше кидаем скрипт Character на персонажа на сцене и возвращаемся к канвасу, где продолжим настраивать наши кнопки.
Так как мы не используем стандартные кнопки Button по причине того, что они могут отловить только событие нажатия, мы будем настраивать изображения через компонент EventTrigger, который позволяет отлавливать кучу других полезных действий.
Поэтому нажимаем кнопку AddNewEventType в компоненте EventTrigger и ищем эти события, после чего добавляем их.
Потому что персонаж будет передвигаться только пока вы “ зажали ” кнопку передвижения, после ее отпускания необходимо будет вызвать команду остановки, чтобы персонаж остановился.
Добавляем его в список действий.
После этого можно запустить и протестировать вызов команд в игре, нажатием на разные кнопки.
Обработка команд
Теперь, когда мы закончили с визуальной частью управления, переходим к самой обработке поступивших команд.
Возвращаемся в скрипт Character, где для начала добавим несколько переменных: переменную направления directionRight, и переключатели onMoving и onMakeJump для движения и совершения прыжка.
Теперь переходим к методу OnDoAction, где разберем действия персонажа на поступившие команды.
Перед тем как выполнить эту команду, необходимо дополнительно проверить, стоит ли на “ земле ” наш персонаж. Для этого добавим простой коллайдер BoxCollider2D персонажу и настроим его.
В методе CheckGround будем проверять, находится ли персонаж на поверхности. Для этого проверим коллайдер персонажа на соприкосновение с землей.
Для этого используем позицию point и размер size коллайдера персонажа.
Далее методом Physics2D.OverlapBox проверим наличие поверхности под “ ногами ”.
Вот так наш персонаж будет обрабатывать поступающие команды от игрока, теперь можно переходить ко второй части статьи – к методам передвижения персонажа.
Физический движок Unity – это самостоятельная система обработки физических объектов и чем больше этих объектов будет на сцене? тем больше ресурсов уйдет на их обработку, так что для лучшей работы игры следует максимально минимизировать их кол-во.
Для персонажа выделим его главные требования: он должен четко взаимодействовать с окружением, которое состоит из коллайдеров, в первую очередь это пол и стены.
Самое главное, с чего нужно начать, так это выбрать методы обработки перемещения персонажа.
Методы обработки
Для обработки движения двух разных типов объектов ( Transform и Rigidbody ) существует два разных метода Update и FixedUpdate – каждый из них используется для своих целей.
Общее у этих методов то, что они оба вызываются через определенное время, Update – каждый кадр, а FixedUpdate – каждый промежуток времени.
В первом случае метод Update вызывается столько раз, сколько позволяет частота кадров в игре, то есть если у вас частота к примеру 60 кадров в 1 секунду, значит, что и метод Update сработает 60 раз за 1 секунду.
Многие начинающие разработчики часто работают с Rigidbody в разных методах: ускоряют, замедляют их, придают им импульсы, бросают и так далее. Но с физическими телами рекомендуется работать именно в методе FixedUpdat. Даже если вы 10 раз измените позицию тела Rigidbody в том же методе Update или в любом другом методе, то все равно эти изменения вступят в силу только в момент вызова метода FixedUpdate, какая частота кадров у вас бы ни была.
В отличие от Transform’а у физического тела Rigidbody есть несколько способов перемещения.
Движение с ускорением
Теперь попробуем применить выбранный тип движения для персонажа, для этого вернемся в скрипт персонажа Character, где создадим новый метод FixedUpdate и пару переменных для перемещения: moveSpeed для скорости движения и jumpForce для силы прыжка.
Сначала определим, в какую сторону персонажу нужно совершать ускорение по оси X. Для этого с помощью переменной directionRight проверим направление персонажа, если ее значение true, значит ускорять объект нужно вправо с положительным значением, если же значение false, то будем ускорять объект влево с отрицательным значением.
Здесь ускорение по оси Y оставляем неизменным – персонаж сам будет обрабатывает вертикальное ускорение.
После проделанных действий наш персонаж сможет двигаться по горизонтали учитывая силу притяжения.
Чтобы проверить, добавим на сцену поверхность с коллайдером.
Теперь попробуем запустить игру и убедиться, что движение работает согласно командам.
Перекинем физический материал в поле Material коллайдера поверхности и снова тестируем.
Изменяя коэффициент трения Friction физического материала можно добиться нужно результата движения по поверхности.
Импульс
Теперь займемся прыжком персонажа. Как было сказано выше, для совершения прыжка физическим телом, будем использовать метод AddForce который придаст объекту импульс движения по вертикали.
Теперь снова вернем переменной onMakeJump исходное значение false для следующего прыжка. Наш персонаж может прыгать по поверхностям, попробуйте запустить и проверить результат.
Снова проверим результат.
Заключение
Вот так легко и просто можно создать систему управления персонажем с помощью команды игрока. Теперь вы запросто сможете подключить к готовому персонажу анимации и добавить в игру другие объекты.