Godot op XREAL AURA: een praktische gids voor native spatiale ontwikkeling
Kort samengevat
Ontdek hoe je Godot op XREAL AURA gebruikt voor native spatiale ontwikkeling, inclusief OpenXR Spatial Containers en anchor-drift-oplossingen.
Je huidige XR-buildpipeline betekent vastzitten aan een desktop, een APK exporteren, sideloaden via ADB, de headset opzetten, een typfout ontdekken en opnieuw beginnen. XREAL AURA doorbreekt die loop volledig, en Godot zit in de launchline-up met een complete editor die op de bril zelf draait. Dat verandert wat 'itereren' betekent voor spatiale ontwikkeling.
Deze gids doorloopt de daadwerkelijke workflow: de editor aan de praat krijgen op AURA, een spatiale scene structureren met OpenXR Spatial Containers, omgaan met het passthrough/see-through-model dat optische brillen anders maakt dan VR-headsets, en de valkuilen die je bij je eerste export bijten.
Waarom optische see-through je ontwerpaannames verandert
XREAL AURA is het eerste optische see-through-apparaat op Android XR. Die ene zin doorbreekt aannames die in de meeste Godot XR-tutorials zitten ingebakken.
Bij een VR-headset rendert de camera van de headset alles. De gebruiker ziet jouw omgeving en niets anders. Bij een optische see-through bril kijkt de gebruiker door de lenzen naar de echte wereld, en wordt jouw gerenderde inhoud eroverheen gecomponeerd. Dit is niet hetzelfde als video-passthrough op een Quest — video-passthrough legt de werkelijkheid vast met camera's en beeldt die opnieuw af, wat latentie en lichtverlies introduceert. Optische see-through heeft nul compositor-latentie voor de echte wereld.
Praktische gevolgen voor je renderbudget:
- Je kunt de echte wereld niet donkerder maken. Zwart is op een transparant display transparant. Je hebt geen ondoorzichtige achtergrond, dus UI die afhankelijk is van contrast tegen donkere panelen faalt in een heldere ruimte.
- Additive-achtige content wint. Helder emissieve content leest goed; donkere, gedesatureerde inhoud verdwijnt. Ontwerp je palet op 2-3x de luminantie die je in VR zou gebruiken.
- Het gezichtsveld is smaller dan VR. Content op extreme hoeken valt buiten het displaygebied. Houd primaire interactiedoelen binnen ongeveer ±30 graden van het midden vooruit.
Als je eerder VR hebt uitgebracht, verwacht dan dat je elk materiaal en elk UI-paneel opnieuw moet afstemmen. Reserveer daar een volledige dag per scene voor.
De Godot-editor instellen op de bril
De editor wordt verspreid via Google Play, niet als een gesideloade APK. Dat is belangrijk, want het betekent dat je hem kunt bijwerken zoals elke andere app.
De instelprocedure:
- Installeer de Godot-editor op XREAL AURA via de Play Store.
- Installeer de bijbehorende Gradle-buildomgeving-app. Deze levert de Android-exporttoolchain, dus je hoeft geen JDK en Android SDK helemaal opnieuw op het apparaat te bouwen.
- Meld je aan met een Android-ontwikkelaarsidentiteit als je builds vanaf het apparaat wilt ondertekenen en publiceren.
- Start de editor — hij opent in een multi-window spatiale werkruimte in plaats van één plat venster.
Dat vierde punt is het interessante. De editor biedt de desktop-achtige functieset, maar gerangschikt als zwevende vensters in de ruimte. Je kunt de Scene-boom in het ene volume houden en de 2D-viewport in een ander.
Wat de on-device workflow je daadwerkelijk oplevert
Het eerlijke antwoord: snelle iteratie op feel, tragere iteratie op assets.
Shaders bewerken, node-transforms tweaken en inputmappings testen op het apparaat waarvoor je ontwikkelt, elimineert de hele export-testcyclus. Die cyclus duurt typisch 3-8 minuten als je buildtijd, overdracht en herstart meerekent. Tien iteraties is een uur kwijt.
Waar het niet mee helpt: grote texture-atlassen importeren, langdurige lightmap-bakes draaien, of iets cpu-intensiefs. Doe dat op een workstation. De realistische verdeling is assetcreatie op de desktop, scene-assemblage en afstelling op de bril.
Spatiale content bouwen met OpenXR Spatial Containers
Godots Android XR-ondersteuning omvat OpenXR Spatial Containers — door het systeem beheerde volumes waar jouw app spatiale content in plaatst. De analogie van het platform zelf is redelijk accuraat: traditionele apps tekenen 2D-content in vensters op een desktop; spatiale apps tekenen 3D-content in containers in een ruimte.
Er zijn twee containertypen die je moet begrijpen voordat je code schrijft:
| Containertype | Het beste voor | Afweging |
|---|---|---|
| Volume | 3D-objecten met echte diepte, world-locked plaatsing | Het systeem kan de volumegrenzen beperken |
| Paneel | UI-oppervlakken, tekst, 2D-games | Gerenderd op een vast vlak; dieptecues zijn plat |
De fout die de meeste ontwikkelaars maken, is volume kiezen voor UI. Tekst in een volume-container wordt door het systeem geschaald en verplaatst op manieren die je niet volledig kunt voorspellen, en je zorgvuldig gepositioneerde radarwidget drijft af. Zet UI in een panel-container en laat het systeem de plaatsing afhandelen.
Werken met de Spatial Container API
Godot stelt spatial containers beschikbaar via OpenXR-extensieklassen. De exacte klassennamen hangen af van je Godot-versie, dus controleer de lijst met functies van de engine voor de huidige spatial container-bindings voordat je productiecode schrijft. Het onderstaande patroon weerspiegelt hoe container-gebaseerde XR-content doorgaans is gestructureerd.
extends Node3D
signal container_created(handle: int)
# Spatial container setup for Android XR.
# Class names are version-dependent; verify against the
# OpenXR extension bindings shipped with your Godot build.
var volume_container: SpatialContainer
var panel_container: SpatialContainer
func _ready() -> void:
var xr_interface: XRInterface = XRServer.find_interface("OpenXR")
if xr_interface == null or not xr_interface.is_initialized():
push_error("OpenXR interface unavailable on this device.")
return
# Volume container for the 3D board.
volume_container = SpatialContainer.new()
volume_container.container_type = SpatialContainer.TYPE_VOLUME
volume_container.extent = Vector3(0.6, 0.4, 0.6) # 60cm x 40cm x 60cm
if volume_container.request_container() != OK:
push_error("Volume container request failed.")
return
# Panel container for the HUD.
panel_container = SpatialContainer.new()
panel_container.container_type = SpatialContainer.TYPE_PANEL
panel_container.extent = Vector3(0.4, 0.4, 0.02)
panel_container.request_container()
add_child(volume_container)
add_child(panel_container)
container_created.emit(volume_container.get_container_handle())
func _process(_delta: float) -> void:
# Containers can be rejected or resized by the system.
if volume_container and not volume_container.is_active():
_handle_container_loss()
func _handle_container_loss() -> void:
push_warning("Volume container lost - repositioning.")
# Never assume the container survives; re-request on loss.
volume_container.request_container()
De kritieke regel is _handle_container_loss(). Door het systeem beheerde containers worden per definitie door het systeem beheerd. De gebruiker loopt weg, de assistent herpositioneert content, of het apparaat reclaimt ruimte. Als je inputafhandeling een containerverlies niet overleeft, staat je app daar met een onzichtbaar bord en een speler die op knoppen ramt.
De valkuil waar bijna iedereen tegenaan loopt: Anchor Drift
Dit is het specifieke probleem, en het is het probleem dat je de meeste debugtijd kost.
Je plaatst een 3D-bord in een volume-container. Je drukt op Play. Alles ziet er goed uit. Je zet de bril af, zet hem twee minuten later weer op, en het bord staat nu een halve meter naar links en 20 graden gedraaid.
Waarom? Omdat je je content hebt verankerd aan de wereld-oorsprong in plaats van aan de container. De wereld-oorsprong op een spatial apparaat is geen stabiele plek — hij wordt gedefinieerd ten opzichte van de startpose van de sessie. Wanneer de sessie opnieuw verankert, beweegt de wereld-oorsprong.
De oplossing is om elk onderdeel van je scene als kind van de container-transform te houden en nooit de globale positie van spatiale content te lezen of schrijven:
# WRONG: assumes world origin is stable
func place_piece(piece: Node3D, board_pos: Vector3) -> void:
piece.global_position = board_pos
# RIGHT: position relative to the container transform
func place_piece(piece: Node3D, board_pos: Vector3) -> void:
piece.position = board_pos # local to container
piece.rotation = Vector3.ZERO
Doe een grep door je project op .global_position en .global_transform voordat je shipped. Elke hit in spatiale content is een potentiële driftbug. Deze klasse van bugs komt ook voor in conventioneel 3D- en multiplayer-werk — anker- en eigenaarsfouten op een gerepliceerde transform veroorzaken exact hetzelfde symptoom van "object teleporteerde voor sommige clients". Daarom is het behandelen van transforms als container-lokaal in plaats van absoluut een gewoonte die de moeite waard is om mee te nemen in elk Godot-netwerkproject.
De oplossing verifiëren
Om te bevestigen dat de verankering klopt:
- Start je scene en noteer de positie van het bord.
- Verwijder het apparaat, wacht 60 seconden en open de app opnieuw.
- Het bord moet op dezelfde fysieke locatie verschijnen ten opzichte van de ruimte, niet op dezelfde offset vanaf waar je ook staat.
- Herhaal met het apparaat in een andere oriëntatie — zittend, dan staand.
Als het afdrijft, bevat je contentboom nog absolute referenties. Als het verspringt maar na de sprong consistent blijft, wordt de container herpositioneerd en volgt je content correct — dat is verwacht gedrag, geen bug.
Omgaan met spelersidentiteit en persistente state
Spatiale apps op Android XR zijn Android-apps. Ze worden onderbroken, ze worden hervat, de gebruiker kan meerdere aangemelde identiteiten op het apparaat hebben en je save-data leeft in hetzelfde account-ecosysteem als al het andere.
De faalmodus is subtiel: een speler speelt ruimtelijk op de bril en opent daarna hetzelfde spel op zijn telefoon. Als je save-state apparaatlokaal is, hebben ze nu twee uiteenlopende werelden en geen manier om ze te verzoenen. Dit oplossen is geen renderingprobleem, maar een account-identiteitsprobleem.
Het zelf goed doen betekent inlogstromen implementeren, een server-side save-store, en — het onderdeel dat iedereen onderschat — conflictbeheer wanneer twee apparaten naar dezelfde save-slot schrijven. Een revisiebewust lees-/schrijfmodel waarbij de client versies vergelijkt en conflicten expliciet oplost, is de enige versie die het contact met echte gebruikers overleeft. Dat vanaf nul bouwen is een klus van meerdere weken; horizOn biedt accountgebonden cloud-save met revisiebewuste reads en writes precies voor dit geval, samen met e-mail-, anonieme, Google- en Apple-authenticatie, zodat dezelfde spelersidentiteit meegaat op de bril en de telefoon.
Welke backend je ook gebruikt, bepaal het conflictbeleid voordat je ship. Last-write-wins vernietigt stilletjes vooruitgang. De speler een prompt geven is beter dan data verliezen.
Best practices voor het uitbrengen op XREAL AURA
- Ontwerp voor omgevingslicht. Test elk UI-paneel buiten 's middags en in een schemerige kamer. Als je tekst in een van beide onleesbaar wordt, verhoog dan het contrast en voeg een subtiele heldere omtreklijn toe in plaats van een donkere schaduw — schaduwen doen niets op een transparant display.
- Houd containers klein en opnieuw aanvraagbaar. Een volume van 60 cm is voor het systeem gemakkelijker betrouwbaar te plaatsen dan een van 2 m. Ga ervan uit dat elke container op elk moment verloren kan gaan en schrijf het herstelpad eerst, niet als laatste.
- Stel een agressief renderbudget. Dit is een bril, geen desktop-gpu. Richt op een frametijd onder 11 ms (90Hz-klasse) met temporal anti-aliasing uit, ten gunste van MSAA, dat minder kost bij spatiale resoluties.
- Zet UI in panels, content in volumes. Vecht niet tegen de plaatsingslogica van het systeem voor tekst. Reserveer volumes voor dingen met echte diepte die de speler vanuit meerdere hoeken bekijkt.
- Verifieer op het apparaat vóór elke mijlpaal. De editor op de bril maakt dit goedkoop. Simulatorresultaten zullen geen anchor drift, luminantiefouten of containerverliesgedrag onthullen.
De volgende stap zetten
De on-device editor is hier de echte kop. Hij comprimeert de spatiale iteratielus van minuten naar seconden, en dat is het verschil tussen een ontwerp afstellen en naar een ontwerp raden.
Begin met het installeren van de editor en de bijbehorende Gradle-app op AURA, en herbouw daarna een klein bestaand project als spatiale scene in plaats van vanaf nul te beginnen — je komt dan onmiddellijk de verankerings- en luminantieproblemen tegen, op content die je al begrijpt. Voeg daarna een 3D-volume-container en een UI-paneel toe en zorg dat beide stabiel blijven gedurende een suspend/resume-cyclus. Als dat standhoudt, ben je klaar om voor het platform te ontwerpen in plaats van ertegen.
Als persistente cross-device spelersstate op je lijst staat, handelt horizOn accountgebonden cloud-save af met conflictoplossing aan clientzijde, zodat je spatiale sessie en je flat-screen sessie in overeenstemming blijven.
Bron: Klaar voor XREAL AURA