Тач-управление — самый критичный компонент геймплея мобильной игры. Ошибки в распознавании касаний сразу ведут к потере игроков. Наш опыт: более 5 лет в индустрии, 30+ реализованных проектов с гарантией точности распознавания жестов от 94%. Свяжитесь с нами, чтобы обсудить ваш проект.
Почему стандартные решения не справляются с тач-управлением?
Unity на мобильных устройствах обрабатывает касания через Input.GetTouch() или новый InputSystem — и между ними пропасть. Старый API не различает тап и начало свайпа до тех пор, пока палец не поднялся. Для игр, где реакция на касание должна быть мгновенной, это неприемлемо. Самая частая ошибка — распознавание жестов на основе TouchPhase.Ended. Разработчик сравнивает позицию Began и Ended, считает вектор — и получает свайп. Работает на девайсе с 60 FPS. На 30 FPS с throttling из-за тепла (типичная картина для бюджетных 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 недели. Стоимость рассчитывается индивидуально после анализа требований к проекту.







