Разработка базового контроллера игрока
Контроллер игрока — первый компонент, который пишется в любом проекте, и первый, который приходится переписывать, если архитектура была выбрана наспех. «Базовый» не означает «простой»: хорошо спроектированный контроллер для 3D-персонажа включает минимум шесть взаимодействующих систем — ввод, детектирование земли, управление velocity, состояния, анимацию и камеру.
Выбор основы: CharacterController vs Rigidbody
CharacterController — кинематический примитив Unity. Его метод Move(Vector3 motion) двигает капсулу с разрешением коллизий, но не участвует в физическом движке: на него не действуют силы, он не толкает Rigidbody-объекты (без кастомного кода) и сам не получает импульсов. Для большинства action-игр это плюс: движение предсказуемо и не зависит от physicsStep.
Rigidbody — полноценный физический объект. Управление через velocity или AddForce позволяет естественные взаимодействия с миром: персонаж катится по склону, его толкают взрывы, он взаимодействует с Joint-объектами. Платой за это является сложность контроля: без правильного PhysicMaterial (frictionCombine = Minimum, dynamicFriction = 0 на капсуле) персонаж застревает на рёбрах геометрии.
Практическое правило: CharacterController для платформеров и action-RPG, Rigidbody для игр с физически значимой средой (гонки, шутеры с ragdoll-взаимодействием, VR).
Структура кода контроллера
Типичная ошибка — один монолитный PlayerController : MonoBehaviour на 800 строк, где перемешаны ввод, физика, анимация и логика состояний. Переиспользовать такой компонент невозможно.
Правильная декомпозиция:
-
PlayerInputHandler— читаетInput System(новая InputSystem черезPlayerInputкомпонент или напрямуюInputAction), пишет вPlayerInputDataструктуру:moveDirection,jumpPressed,sprintHeld,aimPosition -
PlayerMovement : MonoBehaviour— читаетPlayerInputData, управляет перемещением и velocity -
PlayerAnimationController : MonoBehaviour— читает velocity и состояния, управляет параметрамиAnimator -
PlayerCameraController : MonoBehaviour— независимо от движения персонажа, работает сCinemachine Virtual Camera
Данные между компонентами передаются через общую PlayerState структуру или события — не через прямые ссылки компонентов друг на друга.
Детектирование земли и управление прыжком
CharacterController.isGrounded возвращает false при спуске по наклонной поверхности на некоторых кадрах — это баг движка, который присутствует с Unity 5. Надёжное решение: дополнительный Physics.SphereCast вниз от центра капсулы с радиусом 0.9 * capsuleRadius и дистанцией groundCheckDistance. Результат кешируется в isGrounded флаге и используется везде.
Прыжок реализуется через прямое управление вертикальной скоростью в буфере Vector3 velocity:
if (isGrounded && jumpPressed)
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
velocity.y += gravity * Time.deltaTime;
characterController.Move(velocity * Time.deltaTime);
Gravity применяется каждый кадр через deltaTime — это даёт физически корректное ускорение свободного падения. Значение gravity хранится в MovementSettings ScriptableObject и может отличаться от Physics.gravity.y для художественного управления feel-ом.
Интеграция с Animator
Animator управляется через параметры, а не через прямые вызовы Play(). Параметры обновляются в PlayerAnimationController каждый кадр:
-
Speed(float) —magnitudeгоризонтального velocity, нормализованный к maxSpeed -
IsGrounded(bool) — из детектирования земли -
VerticalVelocity(float) —velocity.y, используется для blend между fall/jump анимациями
Для локомоции используется Blend Tree по Speed параметру: Idle → Walk → Run. Это плавнее, чем три отдельных состояния с пороговыми переходами, и не требует ручной настройки transition conditions.
Для поворота персонажа в направлении движения — Quaternion.RotateTowards(current, target, rotationSpeed * Time.deltaTime), не LookAt(): последний телепортирует поворот за один кадр.
Камера: Cinemachine FreeLook
Для 3D TPS-контроллера CinemachineFreeLook с тремя ригами (Top, Middle, Bottom) — стандартный выбор. Камера следует за CameraTarget — пустым трансформом, который плавно следует за персонажем через SmoothDamp. Это предотвращает дрожание камеры при движении по неровной геометрии.
CinemachineCollider extension разрешает проникновение камеры в геометрию — обязателен для любой 3D игры с enclosed пространствами.
Ориентировочные сроки
| Сложность | Состав | Срок |
|---|---|---|
| Простой 2D | Движение, прыжок, переворот спрайта | 1–3 дня |
| 3D базовый | CharacterController, прыжок, Cinemachine, Blend Tree | 4–7 дней |
| 3D полный | + dash, crouch, wall interactions, camera lock-on | 2–3 недели |
| С сетевой репликацией | + Netcode for GameObjects / Mirror синхронизация | +1–3 недели |
Процесс разработки
Сначала — прототип без анимаций: только капсула, движение, прыжок, Camera Follow. Это занимает день и позволяет нащупать feel управления до того, как аниматор вложил время в риггинг. После утверждения feel — интеграция Animator, затем — edge cases: движущиеся платформы, наклонные поверхности, переходы между сценами с сохранением скорости.





