Персонаж в Unity: как собрать игрока и выбрать способ движения

Модель персонажа ещё не является игроком. Игроку нужны управление, движение, столкновения, состояния, изображение и связь с камерой. Эти части можно собрать из нескольких компонентов, чтобы замена модели не ломала правила движения.

Сначала выберем способ перемещения, затем сделаем простой 3D-контроллер на CharacterController. Он подойдёт для проверки ходьбы по плоскости; прыжок, лестницы и анимацию будем рассматривать как отдельные расширения.

ТОП-5 курсов обучения Unity:

Как организовать объект персонажа

У корневого GameObject разместите компонент движения и столкновений. Визуальную модель сделайте дочерней: её можно поворачивать, менять и анимировать независимо от корневой логики. Там же могут находиться точки оружия, эффектов и взгляда камеры.

Здоровье, взаимодействие и инвентарь имеют отдельную ответственность. Им необязательно знать, какая модель сейчас используется. Input читает намерение пользователя, контроллер пытается выполнить движение, Animator отображает фактическое состояние.

Для 2D применяются Rigidbody2D и Collider2D; для 3D — Rigidbody и соответствующие Collider. Компоненты разных физических систем не участвуют в одной симуляции. Пример 2D-игрока есть в руководстве первой игры.

Rigidbody или CharacterController

Rigidbody подходит, когда движение должно участвовать в физической симуляции: силы, импульсы, взаимодействие с другими телами. Управление выполняйте согласованно с физикой, обычно в FixedUpdate. Не перемещайте одновременно один объект через физику и независимую запись Transform каждый кадр.

CharacterController предоставляет капсулу для управляемого движения с обработкой столкновений, ступеней и уклонов. Он не является Rigidbody и не добавляет гравитацию автоматически. Скорость падения и другие правила вы задаёте сами.

Настройки Height, Radius, Center, Step Offset и Slope Limit должны соответствовать масштабу персонажа. Назначение параметров описано в руководстве CharacterController.

Подготовка сцены для примера

  1. В Unity 6 установите Input System. В Active Input Handling выберите Input System Package (New) или Both и перезапустите Editor, если он предложит.
  2. Создайте Plane в позиции (0, 0, 0). Оставьте его Collider.
  3. Создайте пустой GameObject Player в позиции (0, 1, 0). Добавьте CharacterController: Height 2, Radius 0.4, Center (0, 0, 0).
  4. Добавьте дочернюю Capsule с локальной позицией (0, 0, 0). Удалите её Capsule Collider: столкновения уже обрабатывает CharacterController корня.
  5. Поставьте Camera, например, в (0, 6, −8) и поверните по X на 35 градусов, чтобы видеть Plane и игрока.

На Player не добавляйте Rigidbody. Сохраните сцену. Пример читает клавиатуру напрямую для простоты; для полноценной игры действия и переназначение управления лучше организовать через Input Actions.

Минимальный контроллер ходьбы

Создайте SimpleCharacterWalk.cs и прикрепите к Player.

using UnityEngine; using UnityEngine.InputSystem; [RequireComponent(typeof(CharacterController))] public class SimpleCharacterWalk : MonoBehaviour { [SerializeField] private float speed = 4f; [SerializeField] private float gravity = -20f; private CharacterController controller; private float verticalSpeed; private void Awake() { controller = GetComponent<CharacterController>(); } private void Update() { Vector2 input = Vector2.zero; var keyboard = Keyboard.current; if (keyboard != null) { if (keyboard.aKey.isPressed) input.x -= 1f; if (keyboard.dKey.isPressed) input.x += 1f; if (keyboard.sKey.isPressed) input.y -= 1f; if (keyboard.wKey.isPressed) input.y += 1f; } input = Vector2.ClampMagnitude(input, 1f); if (controller.isGrounded && verticalSpeed < 0f) verticalSpeed = -2f; verticalSpeed += gravity * Time.deltaTime; Vector3 velocity = new Vector3(input.x * speed, verticalSpeed, input.y * speed); CollisionFlags flags = controller.Move(velocity * Time.deltaTime); if ((flags & CollisionFlags.Above) != 0 && verticalSpeed > 0f) verticalSpeed = 0f; } }

WASD перемещает игрока по мировым осям X/Z. Ограничение длины ввода предотвращает ускорение по диагонали. Move получает смещение за кадр, поэтому скорость умножается на deltaTime. В отличие от назначения velocity Rigidbody, здесь это необходимое преобразование.

isGrounded отражает контакт при предыдущем перемещении контроллера. Небольшая отрицательная скорость помогает продолжать контакт с землёй. Правила Move описаны в API.

Как проверить и расширить управление

В Play нажмите WASD и диагональные сочетания. Добавьте несколько кубов со стандартными Collider и проверьте обход препятствий. При падении с края Plane игрок должен опускаться; автоматического возврата в этом минимальном примере нет.

Для движения относительно камеры вычисляйте горизонтальные направления камеры и соединяйте их с вводом. Для прыжка добавьте отдельное действие, проверку опоры и начальную вертикальную скорость. Проверяйте уклоны, края и потолок отдельно: удачное движение по ровной плоскости не доказывает готовность платформера.

Анимации связывайте с фактическим движением и состоянием. Если включён Root Motion, заранее решите, кто управляет положением: Animator или контроллер. Два независимых источника движения вызывают рывки и расхождение с коллизией.

Частые причины странного поведения

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

Проверяйте по одному слою: сначала движение без анимации, затем препятствия, камера, эффекты. Такой порядок позволяет понять, какая система внесла ошибку. Настройка камеры разобрана в отдельной статье.

Документация