Разработка сетевого кода для синхронизации игроков
100 мс latency — это не задержка, которую игрок не замечает. В шутере от первого лица за 100 мс противник перемещается на 30–50 сантиметров. Без client-side prediction стрелять в движущуюся цель становится физически некомфортно. Именно поэтому для competitive multiplayer нет варианта «просто синхронизировать позиции через RPC» — нужна полноценная архитектура с предсказанием на клиенте и авторитетным сервером.
Это самая технически сложная часть геймдев-разработки. Ошибки в сетевой архитектуре не исправляются точечными фиксами — они требуют переработки системы.
Почему naive-синхронизация не работает
Простой подход: сервер рассылает позиции всем клиентам. Клиент получает обновление позиции, перемещает объект. При 100 мс RTT объект будет всегда отставать от реального положения на сервере. При движении — видимый lag. При прыжке — «дёрганье».
NetworkTransform с интерполяцией (встроенный в Netcode for GameObjects) — следующий уровень. Клиент не телепортирует объект, а интерполирует между двумя известными позициями. Это убирает визуальное дёрганье, но не решает проблему авторитетности: клиент сам управляет своим персонажем, сервер доверяет клиенту. Это открывает возможности для читерства и не решает lag compensation.
Client-side prediction + server reconciliation — правильное решение для action-игр. Клиент применяет input немедленно локально. Одновременно отправляет input на сервер. Сервер обрабатывает input, возвращает авторитетное состояние. Клиент сравнивает своё предсказанное состояние с серверным и, если есть расхождение, корректирует (rollback + replay). При правильной реализации игрок не замечает никакой задержки — его персонаж реагирует мгновенно.
В Unity NGO (Netcode for GameObjects) это реализуется через NetworkRigidbody с NetworkTransform в Interpolate mode или через кастомный ClientNetworkTransform. В Photon Fusion — встроенный NetworkMecanimAnimator и KCC (Kinematic Character Controller) с prediction out-of-the-box.
Lag compensation для попаданий
Separate хардкорная проблема: игрок стреляет и видит попадание, но на момент выстрела на сервере цель уже в другой позиции. Lag compensation — техника, при которой сервер «перематывает» состояние игровой сцены назад во времени (на величину latency клиента) для проверки попадания.
Реализуется через History Buffer на сервере: каждый тик сохраняем snapshot позиций всех игроков. При обработке shoot-запроса от клиента — восстанавливаем snapshot из прошлого, делаем raycast, возвращаемся к текущему состоянию.
В Mirror это реализуется вручную через NetworkTime.time и кольцевой буфер снапшотов. В Photon Fusion — частично через fusion's built-in lag compensation API (LagCompensatedHit).
Из практики: мобильный тактический шутер, 4 игрока в матче. Первая реализация — simple NetworkTransform + RPC для стрельбы. На устройствах с 80–120 мс latency промахи были очевидны визуально — игрок целится в противника, попаданий нет. После внедрения client-side prediction для движения + lag compensation 150мс на сервере — «честность» попаданий стала приемлемой для casual-аудитории.
Синхронизация состояния игры, не только позиций
State Synchronization выходит далеко за пределы движения персонажей. HP, инвентарь, состояние игровых объектов (двери, ловушки, снаряды) — всё это требует синхронизации. Два основных подхода:
State sync — сервер периодически рассылает полное состояние (или delta) всем клиентам. Надёжно, но дорого по bandwidth при большом количестве объектов.
Event-driven — клиенты рассылают события (игрок открыл дверь), другие клиенты применяют событие локально. Дешевле по bandwidth, но требует идемпотентности событий и обработки потери пакетов.
Для большинства проектов — гибрид: редкие события через reliable RPC, частые обновления (позиции, анимации) через unreliable channel с интерполяцией.
NetworkVariable в NGO — удобная абстракция для синхронизации значений: NetworkVariable<int> Health. Автоматически синхронизируется при изменении, поддерживает OnValueChanged callback. Для HP, score, game state — идеально. Для быстро меняющихся данных (позиция каждый кадр) — избыточно.
Как мы строим сетевой код
Начинаем с network diagram — схема всех игровых систем с указанием, что авторитетно на сервере, что на клиенте, какие данные синхронизируются и с какой частотой. Это основа архитектуры.
Выбор сетевого стека под проект: NGO для Unity с UGS Relay, Mirror + собственный dedicated server, Photon Fusion для competitive action, Nakama для casual с game backend.
Разработка ведётся в NetworkSimulator — тестируем с искусственными задержками 50/100/200 мс и packet loss 1–5%. Проблемы с синхронизацией проявляются только под условиями реальной сети.
| Масштаб задачи | Ориентировочные сроки |
|---|---|
| Базовая синхронизация позиций (2–8 игроков) | 2–4 недели |
| Client-side prediction + lag compensation | 4–8 недель |
| Полная сетевая архитектура с game state sync | 6–12 недель |
| Оптимизация существующего сетевого кода | 2–4 недели |
Стоимость рассчитывается после анализа жанра игры, количества игроков и требований к точности синхронизации.





