В этой статье я расскажу как создать простое управление персонажем от первого лица используя компонент CharacterController.
Для начала создадим пустой объект и назовем его Player. Далее мы будем туда помещать камеру, модель и все остальное.
Теперь в инспекторе добавим в созданный объект компонент CharacterController.
О компоненте 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 - высота коллайдера.
Для нашего персонажа пока оставим значения по умолчанию. Далее добавим в наш пустой объект капсулу, она будет нашей моделью персонажа.
У капсулы уберем коллайдер так как он уже есть у компонента CharacterController.
Теперь перенесем камеру в пустой объект и поместим ее в район "головы" нашего персонажа.
Создадим в инспекторе скрипт отвечающий за управление камерой нашего персонажа. Назовем его CamControl.
Код скрипта выглядит следующим образом:
Вначале определяем значение чувствительности мыши, у меня за 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.
Код скрипта выглядит следующим образом:
Вначале объявляем компонент 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. Этот объект будет отслеживать находится ли персонаж на земле или нет.
Теперь допишем код.
Объявляем переменные 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.
Далее настроим скрипт в инспекторе.
Слой Ground нужно настроить всем объектам по которым должен ходить персонаж.
Теперь сделаем прыжок.
Объявим в конце переменную jumpHeight, она определяет высоту прыжка.
Теперь напишем код для прыжка.
Если нажать клавишу прыжка (пробел) и персонаж на земле (isGrounded = true) то velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity) - это заставит персонажа прыгнуть, а isGrounded = false чтобы мы не могли бесконечно прыгать в воздухе.
На этом все. Теперь мы имеем простое управление персонажем, что подойдет, например, для создания простенького платформера. Отдельные значения вы можете настроить сами в инспекторе.