Проектирование архитектуры программных модулей VR игр
VR-игра, написанная без продуманной архитектуры, превращается в нетронутое минное поле к третьему месяцу разработки. Все классы знают о всех классах, XR Origin напрямую вызывает GameManager, который дёргает AudioManager, который по какой-то причине хранит ссылку на Player — и при попытке добавить поддержку второй платформы вся эта конструкция требует переработки с нуля.
VR добавляет к обычным архитектурным проблемам специфические: несколько источников ввода (левый контроллер, правый, hand tracking, gaze), платформозависимые API (OpenXR vs OVR vs SteamVR), строгие требования к framerate, и необходимость изолировать платформенный код от игровой логики.
Ключевые архитектурные решения для VR
Абстракция над XR-вводом — первое и самое важное решение. Если игровая логика напрямую работает с OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger), портирование на другую платформу потребует правки каждого места, где есть ввод. Правильный подход: Input Abstraction Layer — интерфейс IXRInputProvider с методами GetGripAxis(), GetTriggerAxis(), GetPrimary2DAxis(), и отдельные реализации под каждую платформу/SDK. Игровая логика знает только об интерфейсе.
В Unity это нативно поддерживается через OpenXR + Input System: InputActionAsset с binding'ами под разные устройства, InputAction с callbacks. Один InputActionAsset с двумя binding paths (<XRController>{LeftHand}/trigger и <OculusTouchController>/trigger) работает на любой OpenXR-совместимой платформе без дополнительного кода.
Система взаимодействий (Interaction System) — второй ключевой слой. XR Interaction Toolkit предоставляет IXRInteractable и IXRInteractor интерфейсы, но для сложных проектов этого недостаточно. Нужна кастомная система событий: InteractionEventBus с типизированными событиями (GrabStarted, GrabEnded, HoverEntered, ActivatePerformed) и возможностью подписки без прямых зависимостей между объектами.
State Machine для player state — обязателен в VR из-за специфических состояний: Grounded, Teleporting, InMenu, GrabbingObject, UsingTool. Без явного state machine эти состояния расползаются по bool-флагам в разных компонентах и начинают конфликтовать.
Модульная структура VR-проекта
Рабочая модульная архитектура для Unity VR-проекта выглядит примерно так:
Core — платформонезависимые интерфейсы: IXRInputProvider, ILocomotionController, IHapticController, IHandTrackingProvider. Нет зависимостей на Unity-специфичные или XR-специфичные классы, только C# interfaces.
Platform — реализации Core-интерфейсов: OculusInputProvider, OpenXRInputProvider, SteamVRInputProvider. Платформенный код сосредоточен здесь и только здесь. Bootstrap-компонент на старте сцены определяет активную платформу и регистрирует нужные реализации через Dependency Injection (Zenject или самодельный IoC-контейнер).
XR — логика взаимодействий: XRInteractionManager, HandPresenceController, GrabSystem, LocomotionSystem. Работает через Core-интерфейсы, не знает о конкретных платформах.
Gameplay — игровая логика: механики, прогрессия, ИИ, сохранения. Работает через события от XR-слоя, не знает об XR напрямую.
UI — все игровые интерфейсы через World Space Canvas + UGUI или кастомные spatial UI. Не обращается к Gameplay напрямую — только через события или ViewModel-паттерн.
Такое разделение позволяет тестировать Gameplay-логику через Unity Test Framework без запуска XR-сессии — через mock-реализации Core-интерфейсов.
Производительность как архитектурное ограничение
В VR каждое архитектурное решение оценивается в том числе через призму производительности. 90 fps — это бюджет 11 мс на фрейм. Паттерны, которые безболезненны в обычных играх, в VR убивают framerate:
FindObjectOfType<T>() в Update — полный scene scan каждый фрейм. В VR сцене с 500+ объектами это легко 2–3 мс.
C# allocations в hot path — GC паузы в VR заметны физически, потому что dropped frame в VR это не просто «подтормаживает», это мгновенный motion sickness trigger. В Update/FixedUpdate — нулевые аллокации, всё через object pool и struct-based events.
Синхронные операции в main thread — загрузка ресурсов, сетевые запросы. В VR всё асинхронно: AddressableAssets.LoadAssetAsync, async/await с правильной synchronization context.
Job System и DOTS для VR-проектов с большим количеством физических объектов или NPC — не просто оптимизация, а архитектурное требование. IJobParallelFor для расчётов, которые можно векторизировать (collision checks, proximity queries для grab system), разгружает main thread на 30–50% в типичных сценариях.
Сроки проектирования
| Объём | Ориентировочные сроки |
|---|---|
| Архитектура MVP (одна платформа, 3–5 модулей) | 1–2 недели |
| Мультиплатформенная архитектура (3+ SDK) | 3–4 недели |
| Полная архитектура с мультиплеером и save system | 4–6 недель |
Проектирование включает документацию, диаграммы зависимостей и proof-of-concept реализацию критических модулей. Стоимость рассчитывается после анализа требований и целевых платформ.





