Android XR

Räumliche Inhalte für Android XR mit Unity entwickeln

Lautsprecher

  • Levana Chen

    Softwareentwickler

  • Jennifer Stanton

    Senior Software Engineer

Info

Über den Vortrag

Hier erfahren Sie, wie Sie 3D-Inhalte mit Unity und Android XR in der realen Welt verankern und dauerhaft platzieren können. In dieser Session geht es um das Spatial Entities-Framework, Cloud-Anker und Geospatial APIs. Sie erfahren, wie Sie kontextsensitive Apps erstellen, die sich physische Platzierungen merken und räumliche Daten mehrerer Nutzer über Sitzungen hinweg synchronisieren.

Wir sehen uns die Architektur hinter räumlichen Entitäten an und erfahren, wie digitale Assets an physischen Objekten, Oberflächen und geografischen Standorten verankert werden. Sie lernen praktische Unity-Workflows für die Kartenerstellung, die sitzungsübergreifende Speicherung von Inhalten und die Erstellung von gemeinsamen, standortbezogenen AR/XR-Erlebnissen kennen.

Zusammenfassung

  • AR Foundation bietet eine einheitliche Scripting API für alle XR-Plattformen, die OpenXR-Erweiterungen verwenden. Damit können Sie reale Elemente wie Ebenen und Meshes darstellen und abfragen.
  • Dauerhafte Anker stabilisieren digitale Inhalte über Sitzungen und Geräteneustarts hinweg. Sie können sie mit TrySaveAnchorAsync beibehalten und mit serialisierten GUIDs neu laden.
  • Das Spatial Entities-Framework ersetzt trackable Erweiterungen, um plattformübergreifende Unterstützung und eine bessere Leistung beim Tracking von Elementen wie Begrenzungsrahmen und Markierungen zu bieten.
  • Manager-Komponenten sollten deaktiviert werden, bis Android XR-Berechtigungen gewährt wurden. So werden Fehler bei der Initialisierung des Subsystems vermieden, die durch den eingeschränkten Zugriff auf sensible Umgebungsdaten verursacht werden.
  • Die Geospatial API verwendet Google Cloud ARCore-Dienste und das VPS, um Inhalte an realen Orten im Freien zu positionieren.

Ressourcen

Gemini Notebook

Themen

  • android-xr
  • Einheit
  • ar-foundation
  • openxr
  • spatial-entities
  • Ankeranzeigen
  • geospatial-api

Transkript

Einführung und Übersicht über AR Foundation

  • Okay.

  • Hallo zusammen.

  • In diesem Kurs geht es um die Architektur räumlicher Inhalte auf Android XR mit Unity.

  • Mein Name ist Jennifer Stanton.

  • Ich arbeite bei Unity als Senior Software Engineer.

  • Ich arbeite im XR-Features-Team, insbesondere an AR Foundation und den zugehörigen Paketen, die Augmented und Mixed Reality in Unity ermöglichen.

  • Ich bin Levana Chen vom XR Game Engines-Team von Google.

  • Unsere Teams haben sich darauf konzentriert, Plug-ins und Pakete bereitzustellen, die erweiterte XR-Funktionen und die nahtlose Integration von Game-Engines ermöglichen.

  • Eine der größten Herausforderungen, von denen wir immer wieder hören, ist, dass es sehr viel Arbeit ist, mehrere XR-Plattformen mit derselben Codebasis zu unterstützen.

  • AR Foundation ist die High-Level-API-Schicht für Extended Reality von Unity.

  • Sie können mehrere XR-Plattformen ansprechen, ohne den Code umfassend umschreiben oder mehrere Codebasen verwalten zu müssen. Außerdem erhalten Sie eine Scripting API für AR-Funktionen auf jeder Plattform.

  • So können Sie sich auf die Entwicklung Ihrer App, Ihres Spiels oder Ihrer Umgebung konzentrieren, während Unity sich um die Plattformdetails kümmert.

  • Eine Möglichkeit, wie AR Foundation dies erreicht, sind OpenXR-Erweiterungen.

  • Dabei handelt es sich um eine Reihe offener, branchenüblicher APIs, die von der Khronos Group definiert wurden.

  • OpenXR hat ebenfalls räumliche Entitäten erstellt.

  • Es ist ein Framework für digitale Inhalte, um die physische Welt darzustellen und mit ihr zu interagieren.

  • Räumliche Entitäten bieten ein einheitliches Modell, um reale Elemente als digitale Objekte darzustellen.

  • Ich freue mich, Ihnen einige der neuesten Informationen zu AR Foundation vorstellen zu können, damit Sie mit der Erstellung von XR-Inhalten beginnen können.

  • Als Nächstes gehe ich auf die Funktionen von AR Foundation ein, mit denen Ihre digitalen Inhalte mit der realen Welt interagieren können.

  • Anschließend gehe ich auf die Projekteinrichtung ein, einschließlich Paketen und anderen Abhängigkeiten, damit Sie dies in Ihren Projekten implementieren können.

  • Zum Schluss gehe ich auf einige Funktionen ein, die es nur bei Android XR gibt.

Wichtige AR Foundation-Funktionen

  • Eine der Möglichkeiten, wie AR Foundation die reale Welt digital darstellt, sind Ebenen.

  • Das sind flache Oberflächen in der physischen Umgebung, z. B. Böden, Wände, Decken und sogar Tische und Sofas.

  • Meshes sind 3D-Strukturen, die die Geometrie der physischen Welt darstellen.

  • Und dann gibt es noch Möglichkeiten, mit der realen Welt zu interagieren, nämlich Raycasts.

  • Diese bestimmen, wo ein Strahl digitale Inhalte schneidet.

  • Stellen Sie sich das wie einen Laserpointer vor, bei dem Sie Informationen darüber erhalten, wohin der Laserpointer zeigt.

  • Außerdem gibt es Anker, die helfen, einen Punkt im Raum zu stabilisieren und neu zu positionieren.

  • Ich werde später in dieser Präsentation noch genauer auf Anker eingehen.

  • Alle vier gelten also als AR Foundation-Funktionen.

  • Es gibt noch einige weitere Funktionen, die auf dieser Folie nicht erwähnt werden.

  • Insbesondere Ebenen und Anker gelten als trackbar, da sie die Klasse „ARTrackable“ erweitern und ihre Manager Aktualisierungen aus der Laufzeit verfolgen.

  • Sehen wir uns also die Ebenen an.

  • Für Ebenen gibt es die Komponente „ARPlane“, die eine Echtzeitidentifikation flacher Oberflächen ermöglicht.

  • Sie haben semantische Labels, die Sie abfragen können, um zu erfahren, ob es sich bei der Ebene um einen Boden, einen Tisch, eine Wand usw. handelt.

  • Ebenen haben auch dynamische Grenzen. Wenn sich der Nutzer also in der realen Welt bewegt und mehr von den Oberflächen sieht, werden die Ebenengrenzen in Echtzeit dynamisch erweitert, zusammengeführt und verfeinert.

  • Wir können auch einen Mesh-Collider an die Ebene anhängen, um die Physik zu steuern.

  • Hier sehen Sie ein Beispiel für die Ebenenerkennung.

  • Dies ist die Raycast-Szene aus den AR Foundation-Beispielen, die auf einem Android XR-Gerät ausgeführt wird.

  • Es erkennt dynamische 2D-Polygone in Echtzeit.

  • Sie können eine App mit dieser Funktion erstellen, indem Sie unserem Leitfaden zur Projekteinrichtung folgen oder eines unserer Beispiele oder eine unserer Vorlagen verwenden.

  • Als Nächstes haben wir Meshes.

  • Meshes sind eine AR-Funktion, die 3D-Meshes der Umgebung bereitstellt.

  • Wir können diesen generierten Meshes einen Mesh-Collider hinzufügen, damit Ihre digitalen Inhalte mit realen Objekten interagieren können.

  • Meshes ermöglichen eine überzeugende Objektverdeckung.

  • Ein virtuelles Objekt kann also hinter einem physischen Objekt erscheinen.

  • Wenn sich Ihr digitales Objekt im Raum bewegen kann, können Sie dieselbe Geometrie verwenden, um einen Pfad zu finden, der reale Objekte umgeht.

  • Als Nächstes haben wir Raycasting.

  • Beim Raycasting werden virtuelle Strahlen in Ihre 3D-Szene projiziert, um nach Schnittpunkten zu suchen, ohne dass Sie sich um die komplexe Mathematik kümmern müssen.

  • Der projizierte Strahl kann potenziell mehrere 3D-Objekte in Ihrer Umgebung schneiden.

  • Sie können den Raycast so konfigurieren, dass er nur bestimmte Arten von digitalen Inhalten trifft.

  • Sie können es beispielsweise so konfigurieren, dass es nicht auf Ebenen trifft und nur mit Meshes interagiert.

Pakete und Abhängigkeiten einrichten

  • Sehen wir uns nun die relevanten Pakete an.

  • Diese Pakete arbeiten alle zusammen, um miteinander zu kommunizieren und ein vollständiges XR-Erlebnis zu schaffen.

  • Wie bereits erwähnt, werden in AR Foundation Funktionen wie Ebenen und Anker verarbeitet.

  • Das OpenXR-Plug-in verarbeitet native APIs auf verschiedenen XR-Plattformen. Sie sollten dieses Paket also verwenden, wenn Ihr Gerät OpenXR verwendet.

  • Das OpenXR-Plug-in kann optional mit dem OpenXR Spatial Entities-Paket kombiniert werden, um speziell auf Spatial Entities-Erweiterungen zuzugreifen. Dazu später mehr.

  • Wenn Sie wissen, dass Sie speziell Android XR-Geräte wie XR-Headsets und kabelgebundene XR-Datenbrillen verwenden möchten, benötigen Sie dafür das Unity OpenXR Android XR-Paket.

  • Da all dies dem Plug-in-Muster folgt, sollten die Auswirkungen auf Ihren Code minimal sein.

  • Nicht alle Funktionen sind in allen AR Foundation-Paketen verfügbar.

  • Wenn Sie sich beispielsweise dieses Diagramm ansehen, ist die Meshing-Funktion im Unity OpenXR Spatial Entities-Paket derzeit nicht verfügbar.

  • Mit der XR-Plug-in-Verwaltung können Sie festlegen, welche OpenXR-Funktionen in Ihrem Projekt ausgewählt sind.

  • Wenn Sie sich im Unity-Editor befinden, gehen Sie zu „Edit“ (Bearbeiten), „Project Settings“ (Projekteinstellungen) und dann in der linken Seitenleiste zu „XR Plug-in Management“ (XR-Plug-in-Verwaltung).

  • Hier finden Sie OpenXR-Funktionen und -Funktionsgruppen, die Sie für Ihren Build auswählen und die Auswahl aufheben können.

  • In diesem Screenshot sehen wir beispielsweise alle, die im Android XR OpenXR-Paket enthalten sind.

  • Und dann können Sie diese mit räumlichen Entitäten kombinieren, wenn Sie möchten.

  • Hier ist das Fenster „Package Manager“.

  • Ich habe einige der Pakete hervorgehoben, die Sie in einer typischen XR-Projekteinrichtung sehen könnten.

  • Wie Sie sehen, haben wir AR Foundation, das bereits erwähnt wurde.

  • Außerdem gibt es das OpenXR-Plug-in.

  • Wir haben das Android XR-Paket.

  • Ich habe auch einige andere von anderen Plattformen hervorgehoben, da Sie sicherlich ein Projekt erstellen können, das für mehrere Plattformen kompiliert wird.

  • Und dann haben wir unten rechts noch einige andere Pakete.

  • Composition Layers, die mit OpenXR-Geräten funktionieren, Core Utils, die für alles, was mit XR zu tun hat, sehr nützlich sind, und dann XR Hands und XR Interaction Toolkit, um Eingaben zu erhalten, was ziemlich wichtig ist.

  • Als Nächstes folgt die Projektvalidierung.

  • Auch das ist Teil des XR-Plug-in-Managements.

  • Bei der Projektvalidierung können doppelte Funktionen sowie andere Probleme in Ihrem Projekt erkannt werden, die Sie beheben müssen, damit es funktioniert.

  • In diesem Screenshot habe ich die doppelten Features hervorgehoben.

  • Hier werden also zwei gleiche Funktionen verwendet, z. B. Anker, Ebenen und Raycasts.

  • Der Nutzer hat ausgewählt, dass Duplikate dieser Funktionen aus mehreren Paketen einbezogen werden sollen, und wird nun aufgefordert, eine der Optionen auszuwählen.

Lokale Anker und Persistenz

  • Damit kommen wir zu lokalen Ankern und Persistenz.

  • Anker sorgen dafür, dass digitale Inhalte an den gewünschten Stellen in der Umgebung bleiben, unabhängig von Änderungen am Tracking-Status der AR-Sitzung.

  • AR-Plattformen aktualisieren die Positionen von Ankern im Laufe der Zeit automatisch, damit sie an einer einheitlichen Position bleiben. Anker sind die beste Möglichkeit, dafür zu sorgen, dass Ihre Inhalte an Ort und Stelle bleiben, wenn Sie sich von Ihrem Anker entfernen und dann wieder darauf zugehen.

  • Und was passiert, wenn der Nutzer die App schließt, sie später neu startet und in einer separaten Sitzung zu ihr zurückkehrt?

  • Mit persistenten Ankern können Sie Anker in einer AR-Sitzung speichern und dann in nachfolgenden Sitzungen laden.

  • Sie bleiben über App-Lebenszyklen und Geräteneustarts hinweg erhalten.

  • Hier sehen Sie unser Beispiel für persistente Anker im AR Foundation Samples-Projekt.

  • Die Beispielszene enthält ein Menü mit allen unterstützten Funktionen auf dieser Plattform, z. B. zum Speichern und Laden von Ankern.

  • Damit kommen wir zum Lebenszyklus von persistenten Ankern.

  • Zuerst erstellen Sie lokal einen Anker, der noch nirgendwo gespeichert ist, also nicht im nichtflüchtigen Speicher, sondern nur lokal.

  • Anschließend speichern Sie sie im Speicher.

  • Anschließend können Sie die App neu starten und aus dem Speicher laden.

  • Einige Plattformen, darunter Android XR, unterstützen auch das Löschen oder Aufheben der Persistenz von Ankern.

  • Der Anbieter für räumliche Entitäten unterstützt das automatische Laden aller gespeicherten Anker, sodass Sie nicht jeden Anker manuell über seine ID anfordern müssen.

  • In den Einstellungen für die XR-Plug-in-Verwaltung kannst du die Option „Gespeicherte Anker automatisch laden“ für die Funktion „Räumliche Entitäten: Anker“ auswählen.

  • Das Speichern eines Ankers erfordert nur wenige Codezeilen.

  • Zuerst öffnen wir den Unity-Editor und fügen dem XR Origin-Spielobjekt die Komponente „AR Anchor Manager“ hinzu, um die Szene vorzubereiten.

  • Der Manager aktualisiert die Szene mit getrackten Ankern aus der Laufzeit.

  • Damit kommen wir zum Code.

  • Wenn Sie einen Anker hinzufügen möchten, rufen Sie einfach TryAddAnchorAsync auf und übergeben Sie die Position, an der Sie den Anker platzieren möchten.

    async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
        var result = await manager.TryAddAnchorAsync(pose);
        if (result.status.IsError()) {
            // handle error
            return;
        }
        var anchor = result.value;
    }
  • Als Nächstes entfernen wir Anker.

    void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
        var result = manager.TryRemoveAnchor(anchor.trackableId);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    }
    
    void DestroyAnchorComponent(ARAnchor anchor) {
        Destroy(anchor);
    }
  • Und auch hier ist es im Grunde nur eine Zeile Code.

  • Sie rufen TryRemoveAnchor auf und übergeben die trackbare ID des Ankers.

  • Als der Anker erstellt wurde, wurde ihm bereits eine trackbare ID zugewiesen.

  • Und dann haben wir TrySaveAnchorAsync.

    async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
        var result = await manager.TrySaveAnchorAsync(anchor);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    
        // Save this value, then return it as an input parameter
        SerializableGuid guid = result.value;
    }
  • Sie übergeben einen AR-Anker als Eingabe.

  • Diese Funktion gibt eine SerializableGuid zurück, die den Anker im nichtflüchtigen Speicher identifiziert.

  • Sie können die GUID später beim Laden des Ankers verwenden.

  • Damit kommen wir zum Laden von Ankern.

    async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
        var result = await manager.TryLoadAnchorAsync(guid);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    
        ARAnchor anchor = result.value;
    }
  • Die Funktion, die hier aufgerufen werden soll, ist TryLoadAnchorAsync. Sie übergeben die zuvor serialisierte GUID.

  • Als Ergebnis wird ein AR-Anker zurückgegeben.

  • Das war's auch schon.

  • Mit diesen Funktionen können Sie sowohl lokale als auch persistente Anker einfach verwalten.

  • Das Anker-Tracking ist auf den meisten AR-Plattformen also eine ziemlich rechenintensive Aufgabe.

  • Beachten Sie bei der Arbeit mit Ankern die folgenden Best Practices: Vermeiden Sie es, mehrere Anker sehr nahe beieinander zu erstellen. Überlegen Sie, ob Sie einen vorhandenen Anker in der Nähe verwenden können, anstatt einen neuen zu erstellen. Entfernen Sie Anker, wenn Sie sie nicht mehr benötigen. Wenn Sie eine andere AR-Funktion aktivieren, um die gewünschte Position für einen Anker zu berechnen, überlegen Sie, ob Sie diese Funktion deaktivieren können, sobald der Anker erfolgreich erstellt wurde.

  • Und jetzt übergebe ich an Levana.

Android XR SDK für Unity

  • Danke, Jennifer.

  • Als Nächstes möchte ich Ihnen zeigen, was Google zur Android XR-Entwicklung in Unity beiträgt.

  • Neben den Unity OpenXR-Plug-ins, die Jennifer bisher vorgestellt hat, bietet Google das Android XR SDK für Unity mit zusätzlichen Funktionen an, die auf der Android XR-Plattform verfügbar sind.

  • Dieses SDK enthält viele Funktionen und Pakete. In diesem Vortrag konzentrieren wir uns auf das Android XR-Erweiterungspaket für Unity.

  • Ähnlich wie OpenXR Android XR und OpenXR Spatial Entities ist das Android XR Extension for Unity-Paket also ein OpenXR-Anbieter.

  • Die Architektur dieses Pakets sieht so aus. Die Komponenten können parallel oder unabhängig voneinander arbeiten.

  • Wie alle anderen OpenXR-Anbieter baut auch das Google-Paket direkt auf der Standard-OpenXR-Schnittstelle auf.

  • Hier sehen Sie eine Reihe von Funktionen im Vergleich zu allen anderen Anbietern.

  • So können Sie entscheiden, wann und warum Sie sich für eine bestimmte Option entscheiden sollten.

  • Vielleicht haben Sie eine Frage zu den Markierungen für trackbare und räumliche Entitäten, die in dieser Tabelle angezeigt werden.

  • Eine kurze Anmerkung: Für alle, die bereits Apps und Inhalte für Android XR entwickelt haben, haben wir diese Funktionen über die trackable-Erweiterungen bereitgestellt, die nur unter Android XR funktionieren.

  • Und später, wie Jennifer erwähnte, haben wir als OpenXR-Open-Group gearbeitet und dann die Spatial Entities Extension auf der rechten Seite veröffentlicht, um eine konsistente und plattformübergreifende Erfahrung zu bieten.

  • Derzeit wird die Trackable-Erweiterung zugunsten des Spatial Entities-Frameworks eingestellt.

  • Letzteres ist nicht nur viel leistungsfähiger, sondern bietet auch plattformübergreifende Unterstützung.

Mit räumlichen Entitäten erstellen

  • Sehen wir uns die räumlichen Entitäten genauer an.

  • Neben den von Jennifer erwähnten Ebenen, Raycasting und Ankern wird diese Funktion auch von Anbietern räumlicher Entitäten unterstützt, z. B. Markierungen, die Standard-2D-Barcodes erkennen und decodieren und ihre Position im 3D-Raum verfolgen können, sowie das Bild, das bekannte 2D-Grafiken erkennt und im 3D-Raum verfolgt.

  • Und dann der Begrenzungsrahmen, der das physische Objekt wie Tastatur, Laptop oder Maus identifiziert und seinen Begrenzungsrahmen in der 3D-Pose verfolgt.

  • Im nächsten Beispiel konfigurieren wir die Begrenzungsrahmen-Funktion, die im Erweiterungspaket von Google enthalten ist.

  • Diese Ansicht ist für alle OpenXR-Funktionen ziemlich gleich.

  • Sie müssen also zuerst zur Android XR-Plattform wechseln, dann den OpenXR-Anbieter aktivieren und die OpenXR-Funktion auswählen, mit der Sie entwickeln möchten. Hier wurde beispielsweise die Funktion für den Begrenzungsrahmen für räumliche Entitäten gezeigt. Anschließend müssen Sie die Probleme bei der Projektvalidierung beheben.

  • Sie können damit alle Abhängigkeiten finden, die für ein bestimmtes Feature erforderlich sind, und dann die Konflikte lösen, die durch mehrere Features verursacht werden, die zum selben Subsystem beitragen.

  • Meistens müssen Sie nur eine Funktion auswählen, wenn Sie hier beispielsweise „Anker“, „Ebene“ oder „Begrenzungsrahmen“ verwenden möchten.

  • Und schließlich können Sie einfach die Beispielszene oder Ihre Testszene erstellen.

  • Um zur Laufzeit auf das verfolgbare Objekt zuzugreifen, können Sie einfach die AR-Begrenzungsrahmen-Manager-Komponente hinzufügen. Sie ähnelt der AR-Anker-Manager-Komponente. Anschließend können Sie über die AR Foundation-Schnittstelle darauf zugreifen.

  • Alternativ können Sie auch das Beispiel für ein räumliches Element aus unserem Erweiterungspaket als Vorlage importieren.

  • Hier ist der Hauptunterschied, wenn Sie die AR Foundation-Funktion unter Android XR verwenden.

  • Damit Ihre App die Umgebung des Nutzers besser verstehen kann, benötigt sie in der Regel Zugriff auf die sensiblen Daten der Umgebung.

  • Zum Schutz der Nutzer schränkt Android XR den Datenzugriff hinter den Berechtigungen ein.

  • Das kennen Sie vielleicht schon, z. B. von der normalen Android-Berechtigungsanfrage, etwa für den Zugriff auf die Kamera oder den Standort.

  • Am besten deaktivieren Sie die Manager-Komponente beim Start, entweder im Editor (siehe rechts) oder über ein Skript, z. B. das Awake-Ereignis.

    void Awake() {
        planeManager = GetComponent<ARPlaneManager>();
        planeManager.enabled = false;
        boundingBoxManager = GetComponent<ARBoundingBoxManager>();
        boundingBoxManager.enabled = false;
        permissionUtil = GetComponent<AndroidXRPermissionUtil>();
    }
    
    void OnEnable() {
        StartCoroutine(WaitForPermissions());
    }
  • Nachdem Sie alle erforderlichen Berechtigungen erteilt haben, können Sie den Manager über ein Skript aktivieren, wie es hier mit dem WaitForPermissions-Hilfsprogramm geschieht.

    IEnumerator WaitForPermissions() {
        planeManager.enabled = false;
        boundingBoxManager.enabled = false;
    
        yield return new WaitUntil(() =>
            permissionUtil.AllPermissionGranted());
    
        // Enable after granted permissions and
        // restart subsystems.
        planeManager.enabled = true;
        boundingBoxManager.enabled = true;
    
        // Save permission status.
        permissionGranted = true;
    }
  • So können Sie einen Fehler bei der Subsysteminitialisierung aufgrund unzureichender Berechtigungen vermeiden.

  • Und das ist eine besondere Funktion.

  • Jennifer hat uns gezeigt, wie man mit AR Foundation Anker setzt. Um die Ankerfunktionen unter Android XR zu erweitern, bietet unser Paket auch eine neue Funktion namens „Teilbare Anker“.

  • Diese Funktion repliziert die Funktionen, die derzeit von AR Foundation-Ankern unterstützt werden, und bietet zusätzliche Funktionen wie Georäumliche Anker.

  • Und wie Sie sich vorstellen können, ist der Anker die eigentliche Brücke, die die virtuelle und die physische Welt verbindet.

  • Jennifer hat uns gezeigt, wie man sie erstellt, speichert und lädt, aber das alles ist in einem lokalen Raum passiert, z. B. im Wohnzimmer des Nutzers.

  • Aber was ist mit dem Rest der Welt?

  • Und wie könnten wir sie miteinander teilen?

Geospatial API

  • Und hier kommt die Geospatial API ins Spiel.

  • Damit können Sie einen Georäumlichen Anker basierend auf einem realen Ort erstellen, z. B. Ihrer Lieblingsbuchhandlung oder einem Treffpunkt in einem großen Park.

  • Die Geospatial API kann Ihnen also über das VPS (Virtual Positioning System) einen genauen Geopositions-Tracker zur Verfügung stellen. Das VPS ist wie ein GPS, verwendet aber die Street View-Daten für den Außenbereich, um viel genauere Tracking-Ergebnisse zu liefern.

  • Einige von Ihnen kennen diese Ansicht vielleicht schon, wenn Sie bereits Erfahrung mit der Geospatial-Funktion von ARCore haben.

  • Um auf die Geospatial API unter Android XR zuzugreifen, müssen wir zuerst eine Verbindung zum Backend herstellen, das auf der Google Cloud Platform gehostet wird.

  • Da das Geospatial-Backend tatsächlich vom ARCore-Dienst in Google Cloud unterstützt wird, können Sie genau dieselben Schritte ausführen, um Ihr Google Cloud-Projekt mit ARCore API-Zugriff zu konfigurieren.

  • All das ermöglicht dann die Nutzung der Android XR-Google Cloud-Funktion, die von unserem Erweiterungspaket bereitgestellt wird.

  • Nachdem Sie die Geospatial API aktiviert und den API-Schlüssel aus dem Google Cloud-Projekt abgerufen haben, können Sie diese Funktion aktivieren und die Authentifizierung über das hier gezeigte OpenXR-Einstellungsmenü konfigurieren. Alternativ können Sie sie manuell über die Scripting API TrySetAuthenticationAsync konfigurieren.

    async Task TrySetAuthentication() {
        googleCloudFeature =
            OpenXRSettings.Instance
                .GetFeature<XRGoogleCloudFeature>();
        var result = await googleCloudFeature
            .TrySetAuthenticationAsync(
                strategy, credential);
        if (result.IsSuccess()) {
            // Ready to use for geospatial tracker.
        } else if (result.IsUnsupported())  {
            // Google Cloud feature is not supported
        } else if (result.IsKeylessError()) {
            // Confirm if keyless has been set up properly.
        } else {
            // Handling other common OpenXR errors.
        }
    }
  • Beachten Sie, dass die Android XR-Plattform derzeit nur die Authentifizierung per API-Schlüssel unterstützt. Weitere Anmeldedaten werden in Zukunft unterstützt.

  • Nach der Authentifizierung können Sie dann einen Geospatial Manager verwenden, um auf raumbezogene Funktionen zuzugreifen.

  • Wir empfehlen dringend, vor der Integration die VPS-Abdeckung auf Google Maps zu prüfen.

  • Daher müssen Sie auch Netzwerkzugriff haben, wenn Sie die Funktion verwenden.

  • Der XR Geospatial Manager funktioniert ähnlich wie die AR-Sitzungskomponente von AR Foundation.

  • Sie enthält ein statisches Statusattribut, das die Systemunterstützung und den Tracking-Status des Geospatial-Trackers angibt.

  • Sie können ein Ereignis für eine Statusänderung mit einem Callback wie diesem registrieren.

    void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
        bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
        if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
            // Handle cloud authentication issues.
        } else if (isInitFailed) {
            // Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
        } else {
            // Iterate runtime state change, and handle accordingly.
        }
    }
    
    private void OnEnable() {
        XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
    }
  • Sobald der Geodatenstatus „Wird ausgeführt“ lautet, können Sie diese Manager-Instanz für alle folgenden Funktionen verwenden.

  • Zuerst prüfen wir die VPS-Verfügbarkeit am angegebenen GPS-Standort. Dazu rufen wir mit der Standort-API von Unity den GPS-Wert ab und prüfen dann die VPS-Verfügbarkeit.

    async Task CheckVPSAvailability(CancellationToken token) {
        var location = Input.location.lastData;
        try {
            var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
                location.latitude, location.longitude);
            token.ThrowIfCancellationRequested();
            if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
                // Invalid coordinates, try with another location.
            } else if (result.status.IsError()) {
                // Handle common OpenXR error: result.status.ToOpenXRStatus()
            }  else if (result.value == XRVPSAvailability.Available)  {
                // You may use this pose to attach geospatial anchors.
                var currentGeospatialPose = new XRGeospatialPose(location);
            }
        }
    }
  • Das ist also im Grunde ein Ersatz, wenn Sie die VPS-Unterstützung nicht über die Karte prüfen möchten. Sie müssen jedoch nach draußen gehen, um den tatsächlichen GPS-Status zu prüfen.

  • Außerdem können Sie die Pose mit TryLocate zwischen der Unity-Pose und der Geospatial-Pose konvertieren.

    // Geospatial Pose -> Unity Pose
    var geospatialPose =
        new XRGeospatialPose(Input.location.lastData);
    if (geospatialManager.TryLocate(
            geospatialPose, out XRPoseResult result)) {
        if (result.IsPositionValid ||
            result.IsPositionTracked) {
            transform.position = result.Pose.position;
        }
        if (result.IsRotationValid ||
            result.IsRotationTracked) {
            transform.rotation = result.Pose.rotation;
        }
    }
    // Unity Pose -> Geospatial Pose
    Pose pose = new Pose(
        transform.position, transform.rotation);
    if (geospatialManager.TryLocate(
          pose, out XRGeospatialPoseResult result)) {
        if (result.IsPositionValid ||
            result.IsRotationValid) {
            // You may use for anchor attachment.
        }
    }
  • Anhand des Ergebnisses der VPS-Prüfung oder der Pose-Konvertierung können Sie den räumlichen Anker dann an eine bestimmte Geopose oder einen bekannten Oberflächentyp wie Gelände oder Dach anhängen.

    async void PlaceAnchor(XRGeospatialPose pose) {
        try {
            Result<ARShareableAnchor> anchorResult;
            XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
            if (typeToPlace == XRGeospatialSurfaceType.Default) {
                anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
            } else {
                pose.Altitude = 0;
                anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
            }
            if (anchorResult.status.IsSuccess()) {
                // ARShareableAnchorManager will track the anchor and update it.
            } else {
                // Handle OpenXR failures.
            }
        }
    }
  • Wenn Sie all diese Elemente kombinieren, können Sie wirklich magische räumliche Erlebnisse schaffen, bei denen die reale Welt im Mittelpunkt steht.

  • Hier platzieren wir einen Pfeil, um die Nutzer zum Zielort in der realen Welt zu führen.

  • Okay.

  • Das Android XR SDK ist also nicht das einzige Paket, das wir Unity-Entwicklern zur Verfügung gestellt haben.

  • Das Android XR SDK für Unity von Google enthält jetzt auch das Android XR Interaction Framework und das Android XR Audio-Paket.

  • Wir freuen uns sehr, das Android XR SDK um weitere Funktionen und räumliche Entitäten zu erweitern.

Zusammenfassung und Ressourcen

  • Damit sind wir am Ende der heutigen Session angelangt.

  • Sie können die Roadmap von Unity online verfolgen, um zu sehen, was als Nächstes ansteht.

  • Anfang nächsten Jahres kommt Unity 7, die nächste Generation von Unity.

  • In der Zwischenzeit können Sie diese Tools ausprobieren und ein Projekt mit der Mixed-Reality-Vorlage erstellen oder sich das AR Foundation-Beispielprojekt auf GitHub ansehen.

  • Weitere Informationen zu Spatial Entity und zur Unterstützung unseres Unity-Pakets finden Sie auf der Android-Entwicklerwebsite.

  • Vielen Dank an alle.

  • Wir sind gespannt, was Sie mit AR Foundation und Spatial Entity auf Android XR entwickeln werden.

Code

Code-Snippets

C#-Snippet bei 10:34 in „Lokale Anker und Persistenz“
async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
    var result = await manager.TryAddAnchorAsync(pose);
    if (result.status.IsError()) {
        // handle error
        return;
    }
    var anchor = result.value;
}
C#-Snippet bei 10:43 in „Local anchors and persistence“
void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
    var result = manager.TryRemoveAnchor(anchor.trackableId);
    if (result.status.IsError()) {
        // handle error
        return;
    }
}

void DestroyAnchorComponent(ARAnchor anchor) {
    Destroy(anchor);
}
C#-Snippet bei 11:00 in „Lokale Anker und Persistenz“
async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
    var result = await manager.TrySaveAnchorAsync(anchor);
    if (result.status.IsError()) {
        // handle error
        return;
    }

    // Save this value, then return it as an input parameter
    SerializableGuid guid = result.value;
}
C#-Snippet bei 11:17 in „Lokale Anker und Persistenz“
async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
    var result = await manager.TryLoadAnchorAsync(guid);
    if (result.status.IsError()) {
        // handle error
        return;
    }

    ARAnchor anchor = result.value;
}
C#-Snippet bei 16:45 in „Building with spatial entities“
void Awake() {
    planeManager = GetComponent<ARPlaneManager>();
    planeManager.enabled = false;
    boundingBoxManager = GetComponent<ARBoundingBoxManager>();
    boundingBoxManager.enabled = false;
    permissionUtil = GetComponent<AndroidXRPermissionUtil>();
}

void OnEnable() {
    StartCoroutine(WaitForPermissions());
}
C#-Snippet bei 16:58 in „Building with spatial entities“
IEnumerator WaitForPermissions() {
    planeManager.enabled = false;
    boundingBoxManager.enabled = false;

    yield return new WaitUntil(() =>
        permissionUtil.AllPermissionGranted());

    // Enable after granted permissions and
    // restart subsystems.
    planeManager.enabled = true;
    boundingBoxManager.enabled = true;

    // Save permission status.
    permissionGranted = true;
}
C#-Snippet bei 19:12 in „Geospatial API“
async Task TrySetAuthentication() {
    googleCloudFeature =
        OpenXRSettings.Instance
            .GetFeature<XRGoogleCloudFeature>();
    var result = await googleCloudFeature
        .TrySetAuthenticationAsync(
            strategy, credential);
    if (result.IsSuccess()) {
        // Ready to use for geospatial tracker.
    } else if (result.IsUnsupported())  {
        // Google Cloud feature is not supported
    } else if (result.IsKeylessError()) {
        // Confirm if keyless has been set up properly.
    } else {
        // Handling other common OpenXR errors.
    }
}
C#-Snippet bei 20:24 in „Geospatial API“
void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
    bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
    if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
        // Handle cloud authentication issues.
    } else if (isInitFailed) {
        // Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
    } else {
        // Iterate runtime state change, and handle accordingly.
    }
}

private void OnEnable() {
    XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
}
C#-Snippet bei 20:38 in „Geospatial API“
async Task CheckVPSAvailability(CancellationToken token) {
    var location = Input.location.lastData;
    try {
        var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
            location.latitude, location.longitude);
        token.ThrowIfCancellationRequested();
        if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
            // Invalid coordinates, try with another location.
        } else if (result.status.IsError()) {
            // Handle common OpenXR error: result.status.ToOpenXRStatus()
        }  else if (result.value == XRVPSAvailability.Available)  {
            // You may use this pose to attach geospatial anchors.
            var currentGeospatialPose = new XRGeospatialPose(location);
        }
    }
}
C#-Snippet bei 21:03 in „Geospatial API“
// Geospatial Pose -> Unity Pose
var geospatialPose =
    new XRGeospatialPose(Input.location.lastData);
if (geospatialManager.TryLocate(
        geospatialPose, out XRPoseResult result)) {
    if (result.IsPositionValid ||
        result.IsPositionTracked) {
        transform.position = result.Pose.position;
    }
    if (result.IsRotationValid ||
        result.IsRotationTracked) {
        transform.rotation = result.Pose.rotation;
    }
}
C#-Snippet bei 21:03 in „Geospatial API“
// Unity Pose -> Geospatial Pose
Pose pose = new Pose(
    transform.position, transform.rotation);
if (geospatialManager.TryLocate(
      pose, out XRGeospatialPoseResult result)) {
    if (result.IsPositionValid ||
        result.IsRotationValid) {
        // You may use for anchor attachment.
    }
}
C#-Snippet bei 21:11 in „Geospatial API“
async void PlaceAnchor(XRGeospatialPose pose) {
    try {
        Result<ARShareableAnchor> anchorResult;
        XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
        if (typeToPlace == XRGeospatialSurfaceType.Default) {
            anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
        } else {
            pose.Altitude = 0;
            anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
        }
        if (anchorResult.status.IsSuccess()) {
            // ARShareableAnchorManager will track the anchor and update it.
        } else {
            // Handle OpenXR failures.
        }
    }
}