Тач-управління — найкритичніший компонент геймплею мобільної гри. Помилки у розпізнаванні дотиків одразу ведуть до втрати гравців. Наш досвід: понад 5 років в індустрії, 30+ реалізованих проектів з гарантією точності розпізнавання жестів від 94%. Зв'яжіться з нами, щоб обговорити ваш проект.
Чому стандартні рішення не справляються з тач-управлінням?
Unity на мобільних пристроях обробляє дотики через Input.GetTouch() або новий InputSystem — і між ними прірва. Старий API не розрізняє тап і початок свайпу доти, доки палець не піднявся. Для ігор, де реакція на дотик має бути миттєвою, це неприйнятно. Найпоширеніша помилка — розпізнавання жестів на основі TouchPhase.Ended. Розробник порівнює позицію Began та Ended, рахує вектор — і отримує свайп. Працює на девайсі з 60 FPS. На 30 FPS з тротлінгом через тепло (типова картина для бюджетних Android-пристроїв) дельта між кадрами зростає, і короткий тап за таймером класифікується як свайп.
Правильний підхід — відстежувати рух у фазах Stationary та Moved, додавати поріг за відстанню (sqrMagnitude > threshold) та пороговий час (Time.time - touchStartTime < tapMaxDuration). Unity не надає це з коробки — потрібен власний GestureRecognizer. У проекті на Godot 4 з InputEventScreenTouch та InputEventScreenDrag ситуація трохи краща: рушій розділяє події на рівні API. Але мультитач — окрема історія. index у InputEventScreenTouch дає порядковий номер пальця, і при швидкому знятті одного пальця index-и можуть перемапитися, що ламає логіку двопальцевих жестів.
Як ми будуємо систему жестів?
Для Unity пишемо TouchInputManager як singleton MonoBehaviour, який на кожному кадрі в Update() ітерує Input.touches та розкладає дотики по кінцевих автоматах станів — по одному FSM на кожен активний fingerId. Стани: Idle → Pressing → Tapping/Swiping/Holding. Переходи — за дистанцією та часом. На виході — події: OnTap(Vector2 position), OnSwipe(Vector2 direction, float velocity), OnHold(Vector2 position, float duration), OnPinch(float delta). Ігрові системи підписуються на ці події через C# delegates або UnityEvent, не знаючи нічого про Input.GetTouch.
Для Flutter-ігор на flame engine використовуємо TapDetector, PanDetector, ScaleDetector з пакета flame. Вони коректно працюють поверх Flutter GestureArena — кожен детектор бере участь у конкурсі жестів, і переможець визначається за пріоритетом. Важливо: ScaleDetector та PanDetector конфліктують, якщо не налаштувати behavior: HitTestBehavior.opaque на батьківському віджеті.
Приклад реалізації FSM для одного дотику в Unity
public class TouchFSM : MonoBehaviour { private enum State { Idle, Pressing, Tapping, Swiping, Holding } private State currentState = State.Idle; private Vector2 startPos; private float startTime; public void UpdateTouch(Touch touch) { switch (currentState) { case State.Idle: if (touch.phase == TouchPhase.Began) { startPos = touch.position; startTime = Time.time; currentState = State.Pressing; } break; case State.Pressing: if (touch.phase == TouchPhase.Ended) { float dist = (touch.position - startPos).sqrMagnitude; float duration = Time.time - startTime; if (dist < tapDistanceThreshold && duration < tapMaxDuration) currentState = State.Tapping; else if (dist >= swipeDistanceThreshold) currentState = State.Swiping; else currentState = State.Holding; } break; // ... решта станів } } } Кейс: свайп-атаки в RPG
З нашої практики: в одному проекті (top-down RPG, актуальна LTS версія Unity) потрібні були направлені свайп-атаки з вісьмома напрямками. Проста нормалізація вектора давала нестабільний результат — діагональні напрямки спрацьовували рідше, оскільки користувачі рідко проводять строго під 45°. Рішення: зони допуску ±30° замість стандартних ±22.5°, плюс зважування за швидкістю свайпу — швидкі свайпи менш точні, повільні — точніше. Після цього відсоток коректного розпізнавання зріс з 78% до 94% — власний GestureRecognizer дає приріст точності на 16% порівняно із вбудованим API (за даними Firebase Analytics). Додатково — візуальний фідбек через LineRenderer, який малює слід свайпу із затуханням. Без нього гравець не розуміє, чи прийняла гра його жест.
Порівняння підходів у популярних рушіях
| Рушій | API для тач-вводу | Вбудоване розпізнавання жестів | Мультитач (2+ пальці) | Особливості |
|---|---|---|---|---|
| Unity | Input.GetTouch / InputSystem | Немає (потрібен свій GestureRecognizer) | Так, з FSM по fingerId | Стандарт індустрії, гнучкий, але потребує багато коду |
| Godot | InputEventScreenTouch/Drag | Частково (розділяє тап і свайп) | Так, але індекси можуть перемапитися | Більш високорівневий API, менше low-level контролю |
| Flutter (flame) | TapDetector, PanDetector, ScaleDetector | Повне (GestureArena) | Так, але конфлікти детекторів | Відмінна абстракція, але обмежена кастомізація |
Що входить у роботу?
- Архітектура системи жестів: FSM для кожного fingerId, кастомний GestureRecognizer.
- Інтеграція з ігровими механіками: прив'язка подій до анімацій, стрільби, переміщення.
- Оптимізація для слабких пристроїв: порогові значення, anti-throttling.
- Візуальний фідбек: сліди, індикатори, пульсація.
- Тестування на парку з 50+ реальних пристроїв (Android, iOS).
- Документація та навчання команди.
Як ми гарантуємо результат?
Ми гарантуємо точність розпізнавання жестів не нижче 90% на пристроях з 30 FPS і вище. Наш досвід показує, що правильно спроектована система знижує кількість скарг користувачів на управління в середньому на 60%. Отримайте консультацію по вашому проекту — зв'яжіться з нами, ми оцінимо завдання і запропонуємо оптимальне рішення.
Терміни та вартість
Базова система (тап, свайп, холд) для однієї платформи: 2–4 дні. Повна система з мультитачем, пінчем, кастомними жестами та інтеграцією з ігровими механіками: 1–2 тижні. Вартість розраховується індивідуально після аналізу вимог до проекту.







