Реализация синхронизации состояния мобильной игры

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация синхронизации состояния мобильной игры
Сложная
~5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация синхронизации состояния мобильной игры

Синхронизация состояния — фундамент любого мультиплеерного опыта. Суть проблемы: два устройства должны видеть одинаковую картину игрового мира в один и тот же момент времени, несмотря на задержку сети, потери пакетов и разную вычислительную мощность. Решений несколько, и выбор зависит от жанра.

Snapshot vs State delta vs Event sourcing

Три основных подхода к распределению состояния:

Full snapshot: сервер каждые N мс отправляет полное состояние мира. Просто, но расточительно. При 20 сущностях по 50 байт каждая, 20 Hz — 20 КБ/с на клиента. При 10 клиентах сервер рассылает 200 КБ/с. Подходит для небольших игр.

Delta compression: отправляем только изменения от предыдущего подтверждённого снэпшота. Клиент подтверждает ack: last_received_tick, сервер вычитает delta. Сокращает трафик в 3-10 раз на динамичных сценах. Реализация усложняется: нужно хранить историю состояний для вычисления delta, обрабатывать потерю пакета с delta (без базового снэпшота delta не применить).

Event sourcing: сервер рассылает события (PlayerMoved, BulletFired, EntityDied), клиент воспроизводит их поверх базового состояния. Хорошо для детерминированных игр: шахматы, карточные, стратегии. Плохо для физических симуляций: любой float-погрешности хватает, чтобы состояния разошлись через 30 секунд.

Детерминизм и floating point

Для event sourcing критично: обе платформы (iOS ARM64, Android ARM64/x86) должны давать одинаковый результат одних и тех же вычислений. Стандартный float в C# — детерминированный на одной платформе, но может давать разные результаты на разных CPU.

Решение — fixed-point математика: вместо float 1.5f используем FixedPoint 15000 (масштаб 1/10000). Сложение и умножение целых чисел детерминированы везде. Библиотека FixedMath.Net для Unity, libfixmath для нативного C++.

Godot использует детерминированную физику через _physics_process — все шаги фиксированы. Unity Physics (DOTS) поддерживает детерминизм при одинаковом порядке обработки объектов. Classic Unity PhysX — не детерминирован между платформами.

Client-side prediction и reconciliation

Детальный разбор паттерна для real-time игр:

Client tick 100: применяю ввод локально, отправляю InputPayload{tick:100, input}
Client tick 101-110: продолжаю предсказывать локально
Server: получает InputPayload{tick:100}, симулирует, отвечает StatePayload{tick:100, pos, vel}
Client tick 112: получаю ответ сервера для тика 100
  → Сравниваю предсказанное состояние на тик 100 с серверным
  → Если расхождение > threshold: откат к серверному состоянию тика 100
  → Повторно применяю буфер вводов 101-112

Буфер вводов — circular array фиксированного размера (обычно 64-128 тиков). Каждый элемент: { tick, inputData, predictedState }. При reconciliation — итерация по буферу с повторным применением.

Threshold для reconciliation: не ноль. Если 0.001 юнита расхождения — откат → клиент постоянно подёргивается. Типичный порог: 0.1-0.5 юнита в зависимости от скорости персонажа.

Interpolation для других игроков

Собственный персонаж — client prediction. Остальные игроки — interpolation:

Клиент хранит буфер снэпшотов с серверными метками времени:

[{time: 1000ms, pos: (10,0,5)}, {time: 1050ms, pos: (10.5,0,5)}, ...]

Рендер происходит с задержкой interpolation_delay (обычно 2-3 снэпшота = 100-150 мс при 20 Hz). В момент рендера находим два ближайших снэпшота и линейно интерполируем позицию:

float t = (renderTime - fromState.time) / (toState.time - fromState.time);
renderPosition = Vector3.Lerp(fromState.position, toState.position, t);

Для ротации — Quaternion.Slerp. Для скорости — нужна Hermite interpolation или Catmull-Rom по нескольким точкам — плавнее при изменении направления.

Проблема расхождения (desync)

В детерминированных играх расхождение проявляется не сразу. Стандартная диагностика — state hash comparison: каждый N тиков все клиенты отправляют hash текущего состояния на сервер. Если хэши не совпадают — desync, сервер рассылает полный снэпшот для синхронизации.

Hash вычисляется от критичных полей состояния (позиции, hp, статусы) — не от всего, чтобы не включать несущественные различия (анимационные веса, UI состояния).

Пропускная способность и мобильные ограничения

Мобильный интернет нестабилен. Проектируй под худший сценарий: 150 мс RTT, 5% packet loss, бюджет трафика 50 КБ/с на игрока.

Практические меры:

  • Позиции: int16 вместо float32 с масштабированием (экономия 50%)
  • Ротация: quaternion → два угла int8 (экономия 75%)
  • Entities вне зоны видимости: не рассылать или снизить частоту обновлений
  • Priority-based updates: быстро двигающиеся объекты обновляются чаще

BitPacking библиотеки: NetStack (C#), LiteNetLib BitWriter — упаковка нескольких малых значений в один байт.

Сроки

Snapshot-синхронизация с interpolation для 4-10 игроков: 2-3 недели. Client prediction, reconciliation, delta compression, desync detection: 1.5-3 месяца. Детерминированная симуляция с fixed-point математикой: добавляет 3-6 недель. Стоимость рассчитывается индивидуально.