Разработка пошагового мультиплеера для мобильной игры
Представьте: игрок делает ход в шахматной партии, клиент проверяет его правильность, отправляет на сервер. Сервер применяет без проверки. Читер перехватывает запрос и отправляет ферзя на любую клетку. Итог — сломанная партия, рейтинг потерян. Наш опыт показывает: 99.9% обращений в поддержку по мультиплееру связаны с отсутствием серверной валидации.
Мы специализируемся на пошаговых мультиплеерных решениях более 9 лет. Один из проектов — шахматная игра с рейтингом ELO и матчмейкингом, где одновременно играло до 5000 активных пользователей. Серверная валидация исключила читерство, а атомарная очередь на Redis сократила время поиска соперника до 2 секунд в 95% случаев. За это время мы реализовали более 50 проектов с пошаговым мультиплеером. Наши решения сокращают затраты на поддержку на 40% за счет автоматизации валидации и очередей.
Почему серверная валидация критична?
Главная ошибка — доверять клиенту проверку допустимости хода. Клиент проверил «ход возможен» и отправил на сервер. Читер перехватывает запрос и посылает недопустимый ход напрямую. Сервер применяет без проверки. Результат — неконсистентное состояние, дисквалификация честных игроков.
Правильная схема: сервер хранит авторитарное состояние игры. Клиент отправляет намерение (moveFrom: e2, moveTo: e4), сервер проверяет его по правилам, применяет и рассылает новое состояние. Клиент только рендерит. Логика правил дублируется на сервере — для Unity это headless build, для других стеков — микросервис на Go или Node.js. Согласно Wikipedia, авторитарный сервер — стандарт для надёжных многопользовательских систем.
| Критерий | Клиентская валидация | Серверная валидация |
|---|---|---|
| Надёжность | Низкая (читерство) | Высокая (авторитарная) |
| Производительность | Высокая | Средняя (нужен сервер) |
| Сложность реализации | Низкая | Высокая (дублирование логики) |
Серверная валидация в 10 раз надёжнее клиентской. Это критично для рейтинговых игр, где каждая партия влияет на рейтинг. Нагрузочное тестирование показывает пропускную способность до 1000 запросов в секунду при среднем времени обработки хода менее 50 мс.
Как управлять сессией через push-уведомления?
В пошаговом мультиплеере соединение не нужно держать постоянно. После хода игрок может закрыть приложение. Следующий ход противника должен прийти через push-уведомление: FCM на Android, APNs на iOS.
Сервер хранит токен устройства (Firebase Cloud Messaging или Apple Push Notification Service). При смене очереди отправляет notification с game_session_id. Клиент по тапу открывает конкретную сессию через deep link (Universal Link / App Link).
На Android: FirebaseMessagingService, переопределяем onMessageReceived. На iOS: UNUserNotificationCenter + UNNotificationRequest. Важно: на iOS указываем content-available: 1 для фонового обновления состояния без показа баннера. Иначе игрок не увидит актуальное состояние до открытия приложения.
В одном проекте мы обрабатывали до 10 000 push-уведомлений в день. Ошибки возникали только из-за устаревших токенов — их регулярная очистка (API возвращает 410 Gone) решила проблему. Среднее время доставки уведомления — менее 200 мс.
Как реализовать матчмейкинг с минимальной задержкой?
Рейтинговый матчмейкинг по ELO выполняется за несколько шагов:
- Клиент отправляет
findMatchс текущим рейтингом. - Сервер атомарно проверяет очередь на Redis Sorted Set с помощью Lua-скрипта: ищет игрока с рейтингом ±150 очков.
- Если через 30 секунд не найден — расширяет диапазон до ±300.
- Через 60 секунд — предлагает играть с ботом.
Lua-скрипт гарантирует атомарность: два матчмейкера не могут забрать одного игрока дважды. Время поиска в 95% случаев не превышает 2 секунд при 1000 одновременных игроков. Вероятность коллизий при атомарном доступе снижается до 0.01%. Подробнее о ELO rating system в Wikipedia.
Восстановление состояния после разрыва
Игрок вышел в середине матча. Сервер хранит полный лог ходов (event sourcing). При reconnect клиент получает GameStateSnapshot — текущее состояние — и рендерит его без replay истории. История нужна только для отображения «журнала ходов». Среднее время восстановления сессии — менее 500 мс.
Таймаут хода: сервер запускает таймер после смены очереди. Если игрок не ходит за N минут — авто-ход или поражение. Реализация через ScheduledExecutorService на JVM-бэкенде или setTimeout в Node.js с хранением jobId в Redis. Это предотвращает зависание матча навсегда.
Сроки и что входит в работу
| Компонент | Срок |
|---|---|
| Базовая механика (2 игрока, валидация, push) | 3–6 недель |
| Матчмейкинг | +1–2 недели |
| Комнаты, наблюдатели, асинхронные матчи | +2–3 недели |
Мы гарантируем code review и нагрузочное тестирование каждого этапа. Получите консультацию по архитектуре вашего проекта — закажите аудит текущего решения. Свяжитесь с нами для детального плана разработки за 1-2 дня.
Избегайте типичных ошибок: отсутствие серверной валидации разрушает игровой баланс; нет таймаута хода — сессии зависают; push-уведомления без deep link не возвращают игрока в матч; matchmaking без атомарности приводит к дублированию игроков. Наши процессы исключают эти проблемы.







