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. Файл маленький, завантаження швидке, але відновлення вимагає застосування всіх дельт по порядку. При пошкодженні одного chunk прогресс від нього втрачається.
Для VR бажано гібридний: один повний baseline checkpoint на початок сесії + lightweight дельта-оновлення кожні 2–3 хвилини. При завантаженні: читаємо baseline → застосовуємо дельти → готово. Baseline пересохраняється при завершенні сесії.
Сериалізація трансформів та фізичних об'єктів
Інтерактивні об'єкти у VR мають позицію, ротацію, фізичний стан. JsonUtility не сериалізує 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 тижнів |
Вартість розраховується після аналізу обсягу збережуваних даних, платформи та вимог до надійності.





