Найти тему
Uniread | Блог про Unity

Простое управление персонажем на основе CharacterController

В этой статье я расскажу как создать простое управление персонажем от первого лица используя компонент CharacterController.

Для начала создадим пустой объект и назовем его Player. Далее мы будем туда помещать камеру, модель и все остальное.

Теперь в инспекторе добавим в созданный объект компонент CharacterController.

-2

О компоненте CharacterController

CharacterController позволяет вам легко выполнять движение, ограниченное столкновениями, без необходимости иметь дело с RigidBody.

На CharacterController не влияют силы, и он будет двигаться только при вызове функции перемещения. Затем он выполнит движение, но будет ограничен столкновениями.

У CharacterController можно сразу можно настроить такие свойства как:

  • Slope limit - значение (в градусах) определяющее угол склона на который может забираться персонаж.
  • Step offset - значение определяющее высоту неровности на которую сможет забраться персонаж (зачастую это лестницы).
  • Skin width - Два коллайдера могут проникать друг в друга на значение, равное Skin width. Большое значение Skin width уменьшает дрожание. Малое значение Skin width может привести к застреванию персонажа. Хорошей настройкой является значение 10% от радиуса.
  • Min Move Distance - если персонаж пытается переместиться ниже указанного значения, он не будет двигаться вообще. Это можно использовать для уменьшения дрожания. В большинстве ситуаций это значение следует оставить равным 0.
  • Center - это значение сместит коллайдер в мировом пространстве.
  • Radius - радиус коллайдера.
  • Height - высота коллайдера.

Для нашего персонажа пока оставим значения по умолчанию. Далее добавим в наш пустой объект капсулу, она будет нашей моделью персонажа.

-3

У капсулы уберем коллайдер так как он уже есть у компонента CharacterController.

-4

Теперь перенесем камеру в пустой объект и поместим ее в район "головы" нашего персонажа.

-5

Создадим в инспекторе скрипт отвечающий за управление камерой нашего персонажа. Назовем его CamControl.

-6

Код скрипта выглядит следующим образом:

-7

Вначале определяем значение чувствительности мыши, у меня за 300 единиц. Далее определяем Transform нашего персонажа и значение вращения по оси Х.

В функции Start() напишем что курсор в игре будет заблокирован и не будет мешаться на экране, чтобы потом вернуть курсор уже в игре нажмите ESC.

Функция Input.GetAxis("Mouse X") и Input.GetAxis("Mouse Y") в Unity, для получения значения перемещения мыши по оси X и Y. Их мы умножаем на значение чувствительности (sensitivity) и на Time.deltatime.

playerTransform.Rotate(Vector3.up * camX) позволить вращать модель персонажа при перемещении мыши, то есть модель персонажа будет смотреть туда куда смотрит камера.

rotateX = Mathf.Clamp(rotateX, -90f, 90) ограничивает вращение камеры по оси Х значением 90, то есть камера не задерется за спину персонажа если вы начнете смотреть вверх.

transform.localRotation = Quaternion.Euler(rotateX, 0f, 0f) позволит смотреть вверх и вниз.

Теперь создадим скрипт перемещения нашего персонажа. В объекте Player, в меню инспектора создадим новый скрипт и назовем его PlayerControl.

-8

Код скрипта выглядит следующим образом:

-9

Вначале объявляем компонент CharacterController, переменную ускорения, скорости и гравитации.

Далее в методе Update() объявляем переменные x и z в которых помещается значения горизонтального ввода (клавиши A и D) и вертикального ввода (клавиши W и S).

Vector3 move = transform.right * x + transform.forward * z - в этой строке создается вектор движения move, который объединяет горизонтальное и вертикальное движение. transform.right представляет правую ось объекта, умноженную на значение x, а transform.forward представляет переднюю ось объекта, умноженную на значение z. Это создает вектор движения, который комбинирует горизонтальное и вертикальное движение относительно ориентации объекта.

velocity.y += gravity * Time.deltaTime - здесь скорость по оси y увеличивается на значение гравитации, умноженное на время.

characterController.Move(velocity * Time.deltaTime) - в этой строке скорость velocity применяется к characterController для обновления вертикального положения персонажа на основе скорости, умноженной на время.

На этом этапе мы уже можем двигаться по карте, для проверки можно сделать препятствия из кубов.

Далее создадим в объекте Player еще один пустой объект с названием GroundChecker. Этот объект будет отслеживать находится ли персонаж на земле или нет.

Тут также были добавлены препятствия из кубов
Тут также были добавлены препятствия из кубов

Теперь допишем код.

-11

Объявляем переменные groundCheckerTransform в который мы поместим объект GroundChecker, groundDistance в которой записан радиус GroundChecker'a, groundMask в которой будет записан слой Ground (его нужно создать самому в инспекторе) и булеву переменную isGrounded.

В метод Update() допишем проверку isGrounded.

isGrounded = Physics.CheckSphere(groundCheckerTransform.position, groundDistance, groundMask) - метод возвращает true, если есть какие-либо коллайдеры, пересекающие сферу, определенную положением и радиусом в мировых координатах.

if(isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}

Если isGrounded = true и velocity.y меньше 0 velocity.y будет равна -2.

Далее настроим скрипт в инспекторе.

-12

Слой Ground нужно настроить всем объектам по которым должен ходить персонаж.

Теперь сделаем прыжок.

-13

Объявим в конце переменную jumpHeight, она определяет высоту прыжка.

Теперь напишем код для прыжка.

-14

Если нажать клавишу прыжка (пробел) и персонаж на земле (isGrounded = true) то velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity) - это заставит персонажа прыгнуть, а isGrounded = false чтобы мы не могли бесконечно прыгать в воздухе.

На этом все. Теперь мы имеем простое управление персонажем, что подойдет, например, для создания простенького платформера. Отдельные значения вы можете настроить сами в инспекторе.