Розробка ігрових механік
Механіка, яка виглядала чудово на папері, в руках гравця розпадається за три хвилини. Причина рідко в ідеї — частіше в тому, як вона реалізована технічно. Фізично неправильний стрибок, інвентар, який лагає при 50 предметах, бойова система з race condition на серверній стороні — все це вбиває gameplay feel раніше, ніж гравець встигне оцінити дизайн.
Де механіки ломаються на практиці
Фізика та відчуття управління
Gameplay feel — найскладніша частина. Стрибок у платформері відчувається "дерев'яним" не через цифри в Rigidbody, а через те, як гравітація масштабується в повітрі. Стандартна Physics.gravity = new Vector3(0, -9.81f, 0) дає фізично правильний, але геймдизайнерськи незручний стрибок.
Правильний підхід — окремі коефіцієнти для восходящої та нисходящої фаз:
// Важче падіння — відчуття ваги
if (rb.velocity.y < 0)
rb.velocity += Vector3.up * Physics.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
// Скорочуємо стрибок при відпусканні кнопки
else if (rb.velocity.y > 0 && !Input.GetButton("Jump"))
rb.velocity += Vector3.up * Physics.gravity.y * (lowJumpMultiplier - 1) * Time.deltaTime;
fallMultiplier = 2.5f, lowJumpMultiplier = 2f — стартові значення, які потім ітеруються з геймдизайнером. Це не формула, це стартова точка.
Для шутерів та екшн-ігор критично coyote time (стрибок 80-150 мс після сходження з платформи) та jump buffering (буфер нажиму стрибка 100-200 мс). Без цих деталей управління сприймається як "не відзивчиве", навіть якщо технічно все правильно.
Бойові системи та hit detection
Hitbox vs. hurtbox — базове розділення, яке часто ігнорують у ранніх прототипах та потім переписують під релиз. Hitbox (зона атаки) та hurtbox (зона отримання урану) повинні жити окремо від візуального меша та керуватися через PhysicsScene або OverlapBox/OverlapSphere з правильними LayerMask.
Проблема з OnTriggerEnter для бойових систем: при високій швидкості анімації або при низькому framerate тригер може не сработати взагалі. Надійніше — Frame-based hitbox activation через AnimationEvent + ручна перевірка перекриттів у тій же функції.
Для сітьових ігор бойові механіки потребують server-side validation. Клієнт передбачає результат (client-side prediction), сервер підтверджує. При розбіжності — откат. Без цього будь-який чіт типу speed hack робить хіти в сторону нетронутих противників.
Інвентар та системи предметів
Архітектурна помилка — зберігати стан інвентаря в MonoBehaviour на сцені. При переході між сценами об'єкт знищується або дублюється. Правильно — ScriptableObject як data container + окремий менеджер з DontDestroyOnLoad.
Для складних RPG-інвентарів з крафтом, слотами снаряження та стакингом предметів будуємо через ItemDefinition ScriptableObject (статичні дані: імя, спрайт, вага, теги) + ItemInstance (рантаймовий стан: кількість, durability, modifiers). Це дозволяє серіалізувати інвентар в JSON без посилань на Unity-об'єкти.
Як ми проектуємо та реалізуємо механіки
Прототип до продакшена
Нова механіка починається з ізольованого прототипу у окремій сцені. Ціль — отримати gameplay feel за 2-3 дні, до того як механіка обрастиме залежностями. Якщо стрибок не відчувається правильно у голій сцені з кубом — він не стане кращим після додавання анімацій та ефектів.
Використовуємо геймдизайнерські параметри через ScriptableObject-конфіги з [Range] атрибутами. Дизайнер ітерує значення в редакторі під час Play Mode, не вимагаючи зупинки та перекомпіляції.
State Machine для ігрової логіки
Для складних персонажів з десятками станів (Idle, Run, Jump, Fall, Attack, Stagger, Dead та їх комбінації) використовуємо ієрархічні State Machines. Animator Controller підходить для анімаційної частини, але логіку станів краще тримати в коді через паттерн State з явними переходами — це тестируємо та не залежить від редактора.
Для особливо складних випадків — Unity Visual Scripting або власний граф на основі GraphView API. Але часто достатньо чистого C# з enum-флагами.
Системи, які ми будували
- Процедурна генерація даджунів через BSP-дерево + corridor connection (roguelike)
- Dialogue system з галіфінгом, умовами та voice acting через Ink runtime + Unity integration
- Inventory + crafting + equipment slots з підтримкою save/load через JSON serialization
- Combo-системи для файтингів з frame data (startup / active / recovery frames) та відміною через буфер
- Stealth AI з конусом зору, рівнями тривоги та пам'яттю про останню відому позицію гравця
- Vehicle physics на основі WheelCollider з кастомним suspension tuning
Процес роботи
Аналіз механіки (1-3 дні). Розбираємо, що саме повинна робити механіка, які граничні випадки існують, з якими іншими системами вона взаємодіє. Якщо ТЗ розмите — проводимо ігровий workshop, де програємо механіку без коду.
Прототип (2-5 днів). Мінімальна реалізація для перевірки feel. Ніяких остаточних архітектурних рішень — тільки достатньо, щоб відчути механіку.
Доробка до production-quality (від 1 тижня). Чиста архітектура, edge cases, інтеграція з іншими системами, оптимізація, тесты.
QA. Unit-тесты на логіку (урон, розрахунки статів, переходи станів). Ручне тестування на граничних випадках (що відбувається при одночасному стрибку та атаці? при смерті під час діалогу?).
Терміни залежать від складності механіки: простий стрибок з coyote time — 3-5 днів, повноцінна combat-система з мережею — 3-6 тижнів. Вартість розраховується після аналізу вимог.
Часті помилки при розробці механік
Спиратися на фізичний рушій там, де потрібна передбачуваність. Rigidbody з AddForce дає різні результати при різних framerate. Для платформерів надійніше кінематичний контролер на CharacterController або повністю кастомний рух без фізики.
Не розділяти візуал та логіку. Анімація не повинна керувати станом. AnimationEvent як тригер — окей. AnimationEvent як джерело істини про те, атакує чи персонаж — джерело багів.
Хардкодити числа замість конфігів. float damage = 25f прямо в коді атаки означає, що кожен баланс-твік потребує перекомпіляції. ScriptableObject з параметрами атаки вирішує це, плюс дозволяє робити різні конфіги для різних ворогів.





