XR / OpenXR — VR-приложения в Godot
XROrigin3D, XRCamera3D, XRController3D — базовая VR-сцена для Meta Quest и SteamVR.
Godot имеет встроенную поддержку OpenXR прямо в core, без отдельных пакетов. На фоне Unity это особенно приятно: запуск VR-проекта в Godot — буквально несколько узлов.
OpenXR в Godot — встроено
OpenXR — открытый стандарт Khronos Group для VR/AR. Заменяет SDK от Oculus, SteamVR, Vive Wave. В Godot 4.x OpenXR — часть engine, активируется в Project Settings → XR.
Активация
- Project Settings → XR → OpenXR → Enabled = true.
- Выберите interaction profiles: Oculus Touch, Khronos Simple, Valve Index. По умолчанию включены основные.
- Для Android (Quest): Build Profile → Android, в Export preset включите XR-permissions.
Базовая сцена
Main (Node3D)
└── XROrigin3D ← представляет физическую комнату игрока
├── XRCamera3D ← VR-камера, current=true
├── XRController3D (Left) ← controller_tracker = "/user/hand/left"
│ └── MeshInstance3D ← визуальная модель контроллера
└── XRController3D (Right) ← controller_tracker = "/user/hand/right"
└── MeshInstance3D
Узлы:
XROrigin3D— корень VR-rig. Его позиция = центр игровой комнаты.XRCamera3D— камера, привязанная к headset. Двигается, когда игрок физически ходит.XRController3D— узел, отслеживающий контроллер. Position/rotation обновляются автоматически.
Минимальный код для запуска VR
extends Node3D
var xr_interface: XRInterface
func _ready() -> void:
xr_interface = XRServer.find_interface("OpenXR")
if xr_interface and xr_interface.is_initialized():
print("OpenXR initialized!")
# В Godot для VR-режима нужно выставить viewport
get_viewport().use_xr = true
else:
push_warning("OpenXR not available. Falling back to desktop.")
После этого ваша сцена с XROrigin3D запустится в VR-режиме на подключённом headset.
Без viewport.use_xr = true ваша сцена откроется как обычное desktop-окно, даже если headset
подключён. Это удобно для проверки в “невыезжая в VR”. Когда готовы — выставляете флаг.
Получение input от контроллеров
XR-controller имеет sender’ы для кнопок/осей через input actions, как обычные Input actions в Godot:
- В Project Settings → Input Map создайте action
vr_select. - Привязка: добавьте OpenXR Action Map → Bind to vr_select (через OpenXR Action Map editor).
- В скрипте:
extends XRController3D
func _ready() -> void:
button_pressed.connect(_on_button)
button_released.connect(_on_button_released)
input_float_changed.connect(_on_float_input)
func _on_button(name: String) -> void:
if name == "trigger_click":
_on_trigger_pressed()
func _on_trigger_pressed() -> void:
print("Right trigger pressed")
# Можно выпустить raycast / instantiate projectile
XRController3D имеет встроенные сигналы:
button_pressed(name),button_released(name)input_float_changed(name, value)— для analog axes (trigger, grip)input_vector2_changed(name, value)— для thumbsticks
Grab — взять предмет
Простейший grab без community-плагинов:
extends XRController3D
@export var grab_area: Area3D # ребёнок XRController3D со сферой ~5cm
var held_object: RigidBody3D
func _ready() -> void:
button_pressed.connect(_on_button)
func _on_button(name: String) -> void:
if name == "grip_click":
if held_object == null:
_try_grab()
else:
_release()
func _try_grab() -> void:
var bodies := grab_area.get_overlapping_bodies()
for body in bodies:
if body is RigidBody3D and body.has_method("on_grabbed"):
held_object = body
held_object.freeze = true
held_object.reparent(self)
return
func _release() -> void:
if held_object == null:
return
held_object.reparent(get_tree().current_scene)
held_object.freeze = false
# Можно пересчитать velocity из недавнего движения контроллера
held_object = null
Для серьёзного VR-проекта используйте плагин godot-xr-tools (Asset Library) — он имеет готовые grabbable, teleporter, climbing, hand poses. Аналог Unity XRI.
Hand tracking
Godot 4.6 поддерживает hand tracking через OpenXR Hand Tracking extension:
- Project Settings → OpenXR → Extensions → Hand Tracking = enabled.
- Узлы
XRHandModifier3D(4.6+) илиOpenXRInterface.hand_tracking_enabledв коде. - Получаете доступ к 26 joint’ам каждой руки через
XRPoselookup.
var xr := XRServer.find_interface("OpenXR")
var left_hand_pose := XRServer.get_tracker("/user/hand/left").get_pose("default")
Performance в VR
Те же жёсткие требования, что и в Unity:
- 72 FPS на Quest 2/3, 90+ на PCVR.
- Mobile renderer обязателен для Quest standalone.
- MSAA 4× — стандарт для VR.
- Multiview rendering (single-pass) — включается через Project Settings → Rendering → Performance → Multiview.
- Foveated rendering — Project Settings → OpenXR → Foveation Level (Low/Med/High).
Стандартный пайплайн разработки
- Локальный тест в editor через Quest Link (USB или AirLink).
- После полировки — standalone build для Quest (.apk через Android export).
- Установка через adb или Meta Quest Developer Hub.
Plugin godot-xr-tools
Большинство VR-проектов в Godot опираются на community-плагин godot-xr-tools (через Asset Library). Что он даёт:
- XRToolsFunctionPointer — луч из контроллера для дальнего выбора.
- XRToolsFunctionPickup — продвинутый grab с throw-velocity, snap-points.
- XRToolsFunctionTeleport — teleport-locomotion с правильным fade и validation.
- XRToolsHandPoseController — анимация поз руки в зависимости от того, что схвачено.
- XRToolsMovementProvider — direct/snap/smooth turn, climbing, gliding.
Если планируете серьёзный VR-проект — поставьте сразу.
Сравнение Godot vs Unity для VR
| Godot | Unity | |
|---|---|---|
| OpenXR в core | ✅ встроено | ❌ требует OpenXR Plugin package |
| Interaction toolkit | ⚠️ community (godot-xr-tools) | ✅ official (XRI) |
| Hand-tracking | ✅ с 4.6 | ✅ XR Hands package |
| Performance в VR | Хорошо | Хорошо (Single-Pass Instanced) |
| Magic Leap / Vision Pro | Limited | Лучше (полная поддержка через XR Hub) |
| Размер билда (минимум) | ~40 MB | ~80 MB |
Для hobby-проекта Quest 2 Godot часто проще. Для commercial AAA-VR Unity всё ещё впереди за счёт XRI и broader device support.