Мы настраиваем серверную синхронизацию VR-аватаров — от базовых трансформов до сложных коллизий. Позиции рук и головы обновляются 72–120 раз в секунду; без оптимизации трафик на 8 игроков достигает 50–100 KB/s только на позиции. Добиться плавной синхронизации без перегрузки сети можно с помощью ключевых техник: Dead Reckoning, квантизация, авторитетный сервер. Наша команда имеет 10+ лет опыта в геймдеве и 50+ реализованных VR-проектов, поэтому знает, как решать даже нестандартные задачи.
Как работает Dead Reckoning для рук?
Техника Dead Reckoning пришла из морской навигации и авиасимуляторов. Для VR-аватаров она работает так: вместо позиции на каждый фрейм клиент отправляет позицию + скорость + угловую скорость. Получатель экстраполирует следующую позицию на основе последнего известного состояния + физической модели движения. Когда приходит следующий пакет — сверяем с предсказанной позицией и корректируем.
В Photon Fusion это реализуется через кастомный NetworkBehaviour с [Networked] свойствами для позиции, ротации и производных. Interpolation и Extrapolation настраиваются в NetworkTransform через InterpolationDataSource:
-
Predicted— клиент-авторитетное предсказание, минимальная воспринимаемая латентность для локального игрока -
Interpolated— с задержкой, но гладко для remote игроков -
Auto— Fusion выбирает сам в зависимости от State Authority
Для рук VR принципиально важно, что Predicted режим применяется только к StateAuthority объекта. Удалённые руки всегда интерполируются, и задержка неизбежна — вопрос в том, насколько гладко она скрывается.
Что такое квантизация и дельта-кодирование?
Позиция руки в VR занимает 3 × float32 = 12 байт. Ротация в виде квантерниона — 4 × float32 = 16 байт. Итого 28 байт на одну руку, 56 на две + 28 на голову = 84 байта на игрока без учёта заголовков. Квантизация снижает это до 15–20 байт на игрока — в 4–5 раз меньше исходного размера. Позиция в рабочей зоне VR (3×3×3 м) с точностью 1 мм кодируется в 15 битов на ось. Ротация через сжатый квантернион (три компонента, четвёртый восстанавливается) — 10 битов на компонент.
В Photon Fusion квантизация включается через NetworkTransform.Precision и RotationPrecision. Для кастомных данных используем INetworkStruct с ручной квантизацией через BitStream.
Дельта-кодирование — следующий уровень: передаём только изменение относительно предыдущего состояния. Рука, которая не двигалась (игрок держит объект неподвижно), отправляет почти нулевую дельту, которая компрессируется до нескольких бит. На практике для VR это даёт 30–60% снижение трафика по сравнению с полными позициями каждый тик.
Клиентская или серверная авторитетность: что выбрать?
Это архитектурный выбор с прямыми последствиями для геймплея. Клиентская авторитетность для рук — позиция принимается как есть от клиента — минимальная латентность, максимальная отзывчивость. Но открывает возможность для читов: клиент может присылать «руку» в позиции, куда физически невозможно дотянуться.
Серверная авторитетность — сервер валидирует каждое перемещение руки против физических ограничений (максимальная скорость, зона досягаемости от торса) — устойчиво к читам, но требует RTT-компенсации для ощущения отзывчивости. Для VR-игр без соревновательной составляющей (совместный опыт, кооперативы) — клиентская авторитетность с базовой серверной валидацией аномалий. Для соревновательных VR — серверная авторитетность с агрессивным клиентским предсказанием и rollback.
| Параметр | Клиентская авторитетность | Серверная авторитетность |
|---|---|---|
| Латентность | Минимальная | Выше, требуется компенсация |
| Защита от читов | Низкая | Высокая |
| Где применять | Кооператив, синглплеер | Соревновательные, PvP |
Детали реализации квантизации в Photon Fusion
Для ручной квантизации используйте `INetworkStruct` с полями типа `byte`, `short` или кастомными структурами. Например, позицию можно упаковать в три `short` (15 бит + знак) и распаковать через `BitStream.Read/Write`. Ротацию — через три `ushort` по 10 бит, восстанавливая четвёртый компонент. Такой подход даёт максимальный контроль над точностью и трафиком.Как мы решали проблему рассинхронизации рукопожатия: кейс из практики
Наш клиент — студия, разрабатывающая социальное VR-пространство, — столкнулась с проблемой: игроки «жмут руки», но при RTT 80–120 мс позиции расходились на 5–12 см. Рукопожатие выглядело как пустой жест в воздухе.
Решение: специальный snap протокол. Когда одна рука входит в коллайдер другой (проверяется на сервере), сервер уведомляет обоих клиентов о событии захвата. Оба клиента переходят в режим anchor: один становится ведущим, второй — ведомым. Ведомый интерполирует свою позицию к ведущей с Lerp по 80 мс. Визуально — плавное соединение без телепортации. Свяжитесь с нами — расскажем детали реализации.
Что входит в работу по настройке?
Мы поставляем полный комплект:
- Анализ текущей сетевой архитектуры и выявление узких мест
- Проектирование кастомного NetworkBehaviour под ваши механики
- Реализация с использованием квантизации и дельта-кодирования
- Нагрузочное тестирование с симуляцией 100+ игроков
- Документация по поддержке и дальнейшей доработке
- Поддержка в течение месяца после деплоя
Процесс работы: пошагово
- Аналитика — изучаем текущее сетевое решение, замеряем трафик, определяем требования по точности и латентности.
- Проектирование — выбираем архитектуру (клиентская/серверная авторитетность), определяем схему сжатия.
- Реализация — пишем код: кастомные NetworkBehaviour, квантизация, дельта-кодирование, snap-протокол при необходимости.
- Тестирование — проверяем на разных RTT (20–200 мс), измеряем FPS budget, нагрузку на сервер.
- Деплой — выкатываем на продакшн, настраиваем мониторинг (логгирование задержек, ошибок синхронизации).
Ориентировочные сроки
| Тип задачи | Сроки |
|---|---|
| Базовая синхронизация трансформов (Photon Fusion / Netcode) | 1–2 недели |
| Оптимизация трафика (квантизация + дельта) | +3–5 дней |
| Авторитетный сервер с rollback | 3–6 недель |
| Кастомные взаимодействия (захваты, рукопожатия) | +1–3 недели |
Стоимость рассчитывается индивидуально после аудита вашей архитектуры и требований. Получите консультацию — и мы подберём оптимальное решение.






