tags: [vr-ar]
Разработка систем сохранения прогресса в VR играх
Сохранение в VR — не тот же сценарий, что в обычной игре. Пользователь надевает шлем, играет 20–40 минут, снимает его. Возможно, через день надевает снова. Игра должна восстановить не просто инвентарь и квесты, а пространственное состояние: где стоят объекты в комнате, в каком положении находится механизм, что игрок держал в руках в момент выхода.
Плюс специфика платформ: Quest хранит данные приложения в ограниченном persistent storage, PCVRиспользует стандартный файловый путь, но путь зависит от платформы (SteamVR, OpenXR). Система сохранений должна быть абстрагирована от конкретного хранилища.
Что сохранять: полный state snapshot vs incremental
Два подхода к архитектуре сохранений. Полный snapshot: раз в N минут или по требованию сохраняем всё состояние мира в один JSON/бинарный файл. Просто, надёжно, легко реализовать. Проблема: размер файла растёт с числом объектов, и загрузка большого snapshot занимает несколько секунд — в VR нельзя показать «loading screen» без дискомфорта.
Incremental/event-based: сохраняем только дельту — что изменилось с последнего checkpoint. Файл маленький, загрузка быстрая, но восстановление требует применения всех дельт по порядку. При повреждении одного чанка прогресс от него теряется.
Для VR предпочтителен гибридный вариант: один полный базовый checkpoint на начало сессии + lightweight дельта-обновления каждые 2–3 минуты. При загрузке: читаем baseline → применяем дельты → готово. Baseline пересохраняется при завершении сессии.
Сериализация трансформов и физических объектов
Интерактивные объекты в VR имеют позицию, ротацию, физическое состояние. JsonUtility в Unity не сериализует Transform напрямую — нужно создавать [Serializable] DTO:
[Serializable]
public struct TransformData {
public float[] position; // Vector3 как массив
public float[] rotation; // Quaternion как массив
public bool isGrabbed;
public string grabbedByPlayerId;
}
Для физических объектов дополнительно сохраняем Rigidbody.velocity и angularVelocity — иначе при загрузке объект «зависает» в воздухе, а не продолжает движение. В однопользовательских VR играх это обычно не критично (игра всегда загружается в паузе), но в мультиплеерных сессиях — важно.
Идентификация объектов: каждый сохраняемый объект должен иметь уникальный string ID, устойчивый между сессиями. GUID, присвоенный в [ExecuteInEditMode] или через кастомный Inspector инструмент. Позиция в иерархии сцены — ненадёжный идентификатор, особенно если объекты создаются динамически.
Сохранение состояния XR: HMD и контроллеры
Специфика VR-сохранений: позиция игрока в реальной комнате (XROrigin.transform) и позиция в игровом мире — разные вещи. При загрузке нужно восстановить игровую позицию, но не двигать физически XROrigin — это вызовет телепортацию.
Правильный подход: сохраняем XROrigin.transform.position как базовую точку игрового мира. При загрузке — XROrigin.MoveCameraToWorldLocation(savedPosition) (метод из Unity XR Core Utilities), который корректирует tracking space без физического перемещения риг.
Состояние контроллеров (что держит каждая рука) сохраняем через ID захваченного объекта. При загрузке: восстанавливаем объект → восстанавливаем XRGrabInteractable → вызываем XRBaseInteractor.StartManualInteraction(interactable) для программного захвата.
Облачные сохранения: Unity Cloud Save и Meta Platform SDK
Для Quest есть два варианта облачного хранения. Unity Cloud Save (Unity Gaming Services) — кроссплатформенный, хранит key-value пары, доступен через CloudSaveService.Instance.Data.Player.SaveAsync. Работает на Quest, PC, мобайл. Требует Unity Authentication (анонимный или через аккаунт).
Meta Platform SDK → CloudStorage — нативное хранилище Oculus/Meta. Привязано к Meta-аккаунту, работает только на Meta устройствах. Преимущество: игрок переходит с Quest 2 на Quest 3 — сохранения автоматически переносятся через Meta Cloud.
Рекомендуем двойную запись: локально (в Application.persistentDataPath) + облако при наличии соединения. При загрузке: проверяем дату локального файла vs облако — берём более свежее. Это стандартный конфликт-резолюшн без необходимости показывать пользователю диалог выбора.
| Сложность системы сохранений | Ориентировочные сроки |
|---|---|
| Базовое сохранение (прогресс, инвентарь) | 3–7 дней |
| Полный state snapshot + физические объекты | 1–3 недели |
| Облачная синхронизация + мультиплатформа | 2–5 недель |
Стоимость рассчитывается после анализа объёма сохраняемых данных, платформы и требований к надёжности.





