Розробка базового контролера гравця

Наша компанія з розробки відеоігор веде незалежні проекти, спільно з клієнтом створює ігри та надає додаткові операційні послуги. Досвід нашої команди дозволяє нам охопити всі ігрові платформи та розробити приголомшливий продукт, що відповідає баченню клієнта та перевагам гравців.

Від імерсивних застосунків до ігрових світів і 3D-сцен

Наша виділена команда для VR/AR/MR-розробки, Unity-продакшну і 3D-моделювання та анімації — з власними кейсами і презентаціями.

Відвідати персоналізований сайт
Показано 1 з 1 послугУсі 242 послуг
Розробка базового контролера гравця
Середня
від 2 робочих днів до 2 тижнів
Часті питання

Наші компетенції

Які етапи розробки гри?

Останні роботи

  • image_games_mortal_motors_495_0.webp
    Розробка гри для компанії Mortal Motors
    683
  • image_games_a_turnbased_strategy_game_set_in_a_fantasy_setting_with_fire_and_sword_603_0.webp
    Покрокова стратегія у фентезі сеттингу With Fire And Sword
    862
  • image_games_second_team_604_0.webp
    Розробка ігри для компанії Second term
    491
  • image_games_phoenix_ii_606_0.webp
    3D-анімація – тизер для гри phoenix 2.
    533

Розробка базового контроллера гравця

Контроллер гравця — перший компонент, який пишеться у будь-якому проекті, і перший, який доводиться переписувати, якщо архітектура була обрана наспіх. «Базовий» не означає «простий»: добре спроектований контроллер для 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) — величина горизонтального velocity, нормалізована до maxSpeed
  • IsGrounded (bool) — з детектування землі
  • VerticalVelocity (float) — velocity.y, використовується для blend між fall/jump анімаціями

Для локомоції використовується Blend Tree за параметром Speed: Idle → Walk → Run. Це плавніше, ніж три окремих стани з пороговими переходами, і не вимагає ручного налаштування умов переходу.

Для повороту персонажа в напрямку руху — Quaternion.RotateTowards(current, target, rotationSpeed * Time.deltaTime), не LookAt(): останній телепортує поворот за один кадр.

Камера: Cinemachine FreeLook

Для 3D TPS-контроллера CinemachineFreeLook з трьома ригами (Top, Middle, Bottom) — стандартний вибір. Камера слідує за CameraTarget — порожнім трансформом, який плавно слідує за персонажем через SmoothDamp. Це запобігає тремтінню камери при русі по нерівній геометрії.

CinemachineCollider extension дозволяє проникнення камери в геометрію — обов'язковий для будь-якої 3D-гри з закритими просторами.

Орієнтовні строки

Складність Склад Строк
Простий 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: рухливі платформи, нахилені поверхні, переходи між сценами зі збереженням швидкості.