Wir entwickeln ein Halloween VR Spiel mit Unity 6, XR Interaction Toolkit 3 und Visual Scripting – Teil 2

Weiter geht’s! Nachdem wir im ersten Teil alle Vorbereitungen getroffen haben, um ein Spiel aus Unity auf dem Headset zu installieren und zu testen, machen wir uns heute an unsere eigene Spielszene und behandeln ein paar Grundlagen rund um den Spieler in VR.

Projektstruktur

Wenn du mit dem Finder oder Explorer einen Blick in dein Unity-Projekt wirfst, dann sollte das aktuell ungefähr so aussehen:

Besonderes Augenmerk möchte ich auf den Assets Unterordner legen. Der ist im Wesentlichen für zwei Dinge gedacht:

  1. Zum Speichern von Assets, die speziell für dieses Projekt gedacht sind, z. B. im Asset Store erworbene und importierte Assets.
  2. Zum Speichern deiner eigenen Assets, die du selbst für das Spiel entwickelst.

In der Regel haben wir in diesem Ordner völlige Gestaltungsfreiheit und jeder Unity-Entwickler hat seine eigene Vorstellung davon, wie die Dateien am besten organisiert werden. Deshalb zeige ich dir hier kurz, wie ich die Dateien im Folgenden organisieren werde. Es steht dir aber frei, davon abzuweichen.

Anmerkung: Selbst bereits durch Render-Pipeline, XRIT oder den Sample Project Import angelegte Ordner können in der Regel gefahrlos innerhalb des Assets-Ordners verschoben werden. Nur gelegentlich findet sich z. B. ein Plugin, das Verzeichnisnamen hartcodiert hat und unbedingt auf oberster Ebene im Assets-Ordner liegen bleiben muss. Wir werden die von Dritten angelegten Ordner dennoch der Einfachheit halber nicht verschieben.

Für mich haben sich drei Asset-Kategorien herauskristallisiert, die ich in Unity-Projekten am häufigsten verwende:

  1. Szenen. Die sind in der Regel der Einstiegspunkt in die Arbeit. Ich springe gerne zwischen Spielszenen (Leveln) und Testszenen für bestimmte Funktionalität hin und her.
  2. Module. Dieser Begriff stammt nicht aus dem Unity Vokabular, sondern ist meine eigene Schöpfung für eine Sammlung von thematisch zusammenhängenden Assets. Wenn ich in unserem Spiel bspw. einen Skelett-Gegner entwickele, dann könnte ich das 3D Modell in einen “Models” Ordner mit vielen anderen Models packen, die Animationen in einen “Animations” Order, die Texturen… usw. Es hat sich für mich aber als effizienter herausgestellt, diese Skelett-Gegner-spezifischen Elemente nahe beieinander zu speichern.
  3. Prefabs. Das sind klassische und in der Regel statische Unity-Prefabs, wie bspw. Levelbauteile.

Damit ich diese Ordner schnell in meinem Unity-Projekt finde, nutze ich einen numerischen, aufsteigenden Präfix, d.h. 000_Scenes, 010_Modules, 020_Prefabs. Weit hinten platziere ich Ordner mit Dateien, die sich erfahrungsgemäß selten ändern, wie z. B. Fonts. Die 10er Schritte nutze ich, damit ich ggf. in einem wachsenden Projekt noch etwas dazwischen schieben kann, ohne direkt viel umbenennen zu müssen – wer jemals BASIC programmiert hat…! Mit diesem Schema erscheinen meine eigenen Ordner in der Regel vor den Ordnern von Dritten. Und je nach Projekt lege ich einen Ordner 950_ThirdParty an und verschiebe diese ebenfalls.

Die erste Spielszene

Lege jetzt bitte zunächst den Ordner für unsere eigenen Szenen an. Suche im Project View (1) den Ordner Assets (2), klicke rechts darauf und wähle dann im Kontextmenü Create (3) → Folder (4). Benenne den neu angelegten Ordner dann 000_Scenes (5).

Jetzt klicke nochmals rechts auf den neu angelegten Ordner, wähle Create → Scene → Scene und lege eine Szene an. Nenne sie Graveyard, denn wir werden hier nach und nach den ersten Teil der Spielidee umsetzen.

Öffne die Szene durch einen Doppelklick.

Die Szene ist fast komplett leer, sie enthält nur ein “Directional Light” und eine “MainCamera” in der Hierarchy. Die “Main Camera” kannst du direkt löschen, wir werden sie nicht brauchen.

Damit wir weiterarbeiten und testen können, müssen wir die Szene zur Startszene in unserer App machen. Die XRIT Demo Scene hingegen brauchen wir hier nicht mehr. Klicke auf File → Build Profiles und dann auf “Scene List”. Klicke dort auf “Add Open Scenes”, um die neue Szene hinzuzufügen, und entferne mit einem Rechtsklick gefolgt von “Remove Selection” die DemoScene. Jetzt kannst du den Dialog wieder schließen.

Damit wir uns in VR durch die leere Szene bewegen können, benötigen wir noch mindestens zwei Dinge:

  1. Eine Repräsentation des Spielers. In XR nennen wir das ein Rig (auch Camera Rig oder Player Rig), da es den “Aufbau” eines Spielers nachbildet. Der kann je nach Anforderung beliebig komplex werden und wir werden das im Folgenden noch im Detail besprechen. Zunächst ist nur wichtig zu wissen, dass große Teile der VR Welt oft physik-basiert sind, d.h. die Gegebenheiten der echten Welt simulieren. So kommt ein großer Teil der Immersion zustande! Das gilt auch für den Spieler, auf den z. B. Gravitation wirkt. Würden wir uns also in einer völlig leeren Spielwelt bewegen, würden wir ins Leere fallen.
  2. Dementsprechend benötigen wir darüber hinaus eine Oberfläche, auf der wir uns bewegen können. Wichtig ist, dass diese Oberfläche mit einer Collider-Komponente ausgestattet ist.

Den zweiten Teil erledigen wir schnell, bevor wir uns dem Rig zuwenden. Dazu klicken wir in einem freien Bereich der Hierarchy mit rechts und wählen dann 3D Object → Plane.

Übrigens: standardmäßig erzeugt Unity Objekte “vor dir” in Blickrichtung der aktuellen Editorkamera. Das bedeutet, dass du gelegentlich sicherstellen solltest, dass die Objekte nicht an ungewünschter Stelle positioniert werden. Wir wollen zunächst alles am Ursprung (0, 0, 0) positionieren. Bitte prüfe deshalb rechts im Inspector die Position der Ebene, sie sollte (0, 0, 0) sein (1). Falls nicht, kannst du X/Y/Z manuell bearbeiten oder mit rechts auf die “Transform” Überschrift klicken und “Reset” auswählen. (Man kann in den Einstellungen auch festlegen, dass neue Objekte immer bei (0, 0, 0) angelegt werden, ich verwende diese Option jedoch nicht.)

Im Inspector kannst du die Ebene auch etwas vergrößern, z. B. von Standard-Scale (1, 1, 1) auf (5, 5, 5) (2). Wie du siehst, hat die Ebene bereits einen Mesh Collider (3), so dass auch diese Anforderung abgehakt ist. Wenn wir den Spieler jetzt auf dieser Ebene platzieren, bleibt er auch darauf stehen.

Aber wie kriegen wir einen Spieler? Was ist der Spieler eigentlich in VR? Und wie können wir das nachbilden? Diesen Fragen wollen wir uns jetzt widmen.

Der Spieler in XR: Grundlagen

In diesem Kapitel möchte ich ein grundsätzliches Verständnis dafür aufbauen, was der virtuelle Spieler eigentlich alles benötigt, um in der virtuellen Welt für unterschiedliche Typen von menschlichen Spielern zu funktionieren. Das ist aber viel Theorie und vor allem viel Kratzen an der Oberfläche, weil mehr Details den Rahmen sprengen würden. Wenn du also lieber schnell zu Ergebnissen kommen möchtest, dann kannst du dieses Kapitel auch überspringen.

Das Headset auf dem Kopf

Wenn wir das Headset – auch HMD, head-mounted display – aufsetzen, dann werden zwei leicht versetzte Bilder in die zwei Linsen projiziert. Das Gehirn verarbeitet das genau wie die Bilder aus der echten Welt zu einem dreidimensionalen Bild. Um die Orientierung des Headsets im Raum zu ermitteln, ist das Headset mit diverser Hardware ausgestattet. Die Hardware stellt der Software diese Daten zur Verfügung und es liegt in der Verantwortung der Software, in VR die Bilder anhand dieser Informationen richtig zu generieren bzw. in AR/MR Zusatzinformationen richtig zu augmentieren.

Wir benötigen also eine Kamera, die unsere Spielwelt aufzeichnet und an das Headset liefert. (In einigen Szenarien gibt es auch zwei Kameras, aber die lassen wir der Einfachheit halber hier außen vor.)

Die Orientierung des Headsets wird von der Hardware in Form von Position und Rotation zur Verfügung gestellt. In der Fachsprache verwenden wir dafür das englische “Pose“, und weil diese ständig von der Hardware getracked wird, oft auch “tracked pose”. Diese Pose wird während der Laufzeit ständig auf die Kamera angewandt. Wenn das nicht oder zu langsam passiert, führt das schnell zu Desorientierung beim Spieler. Unity hat dieses Prinzip für uns abstrahiert, denn es wird genau so z. B. bei den Controllern benötigt.

Die Pose ist relativ zu einem Bezugspunkt: der ist entweder die initiale Position des Geräts im Raum (in XRIT heißt die Option “Device”), oder, wenn das Headset in der Lage ist, den Untergrund zu erkennen, die Position auf dem Untergrund (“Floor”). Bei der Quest ist letzteres der Fall. Wenn das Headset nicht in der Lage ist, die eigene Position im Bezug zum Untergrund zu erkennen, dann muss durch die Anwendung auch noch eine Standard-Spielerhöhe vorgegeben werden, damit man das Spiel nicht aus “Froschperspektive” beginnt.

Ausgerechnet das ausgereiftere “Floor” Tracking bringt allerdings einen Nachteil mit sich. Wenn ich als Spieler stehend starte und mich dann entscheide, sitzend fortzusetzen, wandert die Kamera beim Hinsetzen durch das Positionstracking des Headsets auf die ursprüngliche Bauchhöhe (die Pose ändert sich). Wenn der Spieler sich in dieser Position weiter durch die Spielwelt bewegt, mag das merkwürdig wirken und Einschränkungen mit sich bringen.

Daher bieten Spiele entsprechende Konfigurationsmöglichkeiten. Wenn man auf “sitzend” wechselt korrigiert das Spiel einen konfigurierbaren, vertikalen Versatz (Y-Offset) und damit die Kameraposition entsprechend nach oben.

Das folgende Bild verdeutlicht das beschriebene Szenario mit dem “Device” als Ursprung. Der Einfachheit halber beschränken wir uns auf Veränderungen der Position, nicht der Rotation:

Das Spiel beginnt mit einem bestimmten Versatz und dem Kopf und Headset in Ursprungsposition. Setzt sich der Spieler, sendet das Headset die korrigierte Pose (hier eine Verschiebung der Position um 40cm nach unten) an das Spiel, das die Kamera entsprechend tief positioniert. Da der Spieler aber dauerhaft sitzend weiterspielen möchte und das Spiel ihn in dieser neuen Haltung weiterhin als “stehend” betrachten soll, muss der Versatz (Y-Offset) um 40cm erhöht werden.

Wichtig ist zu erwähnen, dass die Möglichkeit der Rotation des Headsets und damit der Kamera durch den menschlichen Körper beschränkt ist. Ein gesunder Mensch kann seinen Kopf normalerweise rund 80 Grad nach links oder rechts rotieren. Wer stehend spielt und mehr Freiheit braucht, kann einfach den Körper rotieren. Wer sitzend auf einem nicht drehbaren Stuhl spielt, braucht ggf. weitere Möglichkeiten, um die Drehung des Körpers zu simulieren. Dazu kommen wir weiter unten bei Locomotion.

Die Controller in der Hand

Wie schon oben geschrieben, ist das Prinzip zur Verortung der Controller im Raum identisch: die Orientierung (Pose) wird letztendlich an die Software gemeldet und die entscheidet, was damit zu tun ist.

Die Pose der Controller ist genau wie die des Kopfs relativ zum Ursprung, in diesem Fall wieder der initialen Geräteposition.

Zusätzlich haben die Controller noch einige Buttons und Thumbsticks. Einige Buttons können dabei nur “gedrückt” oder “nicht gedrückt” sein, während andere wie z. B. die Trigger- und Grip-Buttons an den Quest-Controllern die Stärke als Wert zwischen 0 und 1 liefern. Ebenso liefern die Thumbsticks Werte zwischen -1 und 1 jeweils auf der horizontalen und vertikalen Achse.

Wichtig ist, dass die Controller sich unabhängig von der Kamera bewegen können. Wenn man den Kopf weit dreht, wandern die Controller nicht mit. Diese Erkenntnis wird sich später in der Struktur des XR Rigs im Unity-Projekt widerspiegeln.

Hand-Tracking

Wenn Hand-Tracking unterstützt wird, dann muss die Orientierung der Hände – genau wie die der Controller oben – vom Headset interpretiert und geliefert werden und die Hände wären dann anstelle der Controller Teil des XR Rigs.

Da den Händen die Buttons fehlen, haben sich hier verschiedene Gesten etabliert, die ebenfalls erkannt werden müssen.

Wir werden in diesem Projekt allerdings kein Hand-Tracking unterstützen und belassen es dementsprechend bei der kurzen Nennung.

Locomotion

Locomotion bezeichnet die Methode, mit der sich der Nutzer in XR fortbewegt. Da der physische Raum oft begrenzt ist, müssen verschiedene Techniken eingesetzt werden, um dem Nutzer das Gefühl zu geben, er könne sich in einer potenziell unbegrenzten virtuellen Welt bewegen. Locomotion beschreibt also alle Methoden und Mechanismen, die genutzt werden, um diese virtuelle Bewegung zu realisieren.

Wie auch im echten Leben ist in VR die Blickrichtung von der Bewegungsrichtung getrennt und der Spieler kann den Körper drehen, während er einen Punkt im Raum fixiert oder den Kopf starr hält. Diese Rotation des Körpers kann entweder durch reale Drehung und das Positionstracking des Headsets bewerkstelligt werden oder durch Drehung des virtuellen Spielers im virtuellen Raum per Knopfdruck. Wie oben erwähnt benötigen z. B. sitzende Spieler diese Möglichkeit, weil sie sich anders nicht um 180 Grad drehen können. Ein Teil von Locomotion ist also die Möglichkeit, den Körper im virtuellen Raum zu drehen. Diese Drehung kann stufenlos oder stufenweise stattfinden.

Der andere Teil ist die Fortbewegung im virtuellen Raum. Hier werden verschiedene Varianten unterschieden und ich nenne einige, die mir auf Anhieb einfallen – ohne Anspruch auf Vollständigkeit, denn findige XR Entwickler denken sich ständig etwas Neues aus:

  1. Physische Bewegung. Der Nutzer bewegt sich in seinem Raum und diese Bewegung wird 1:1 in die virtuelle Welt übertragen. Diese Variante ist zweifellos die immersivste, aber sie ist gleichzeitig auch die seltenste, denn die wenigsten Nutzer haben ausreichend freie Fläche zur Verfügung. Mixed Reality Vorstöße mit Pass-Through verbessern die Erfahrung insofern, als dass man sich auch in einem kleinen Raum gut orientieren und bewegen kann.
  2. Smooth Locomotion. Dieser Begriff wird verwendet, wenn der Spieler in der realen Welt an einer Stelle im Raum bleibt, sich aber meist durch Nutzen eines Thumbsticks kontinuierlich durch die virtuellen Welt fortbewegt. Da der Spieler sich hierfür nicht echt fortbewegen muss, spielt es keine Rolle, ob er dabei sitzt, steht oder gar liegt.
  3. Teleportation. Auch hier verweilt der Spieler in der echten Welt an einer Stelle. In der virtuellen Welt wählt er allerdings – je nach Szenario aus fest vorgegebenen Punkten oder frei in der Spielwelt – ein Teleportationsziel und wird dann dorthin gebeamt.
    Diese Art der Fortbewegung wird heute vorrangig aus Komfortgründen genutzt, die wir weiter unten noch beleuchten. Mit ihr einher gehen auch Vor- und Nachteile im Spieldesign: Vorteilhaft ist, dass die Positionen, von denen man interagieren kann, begrenzt sind: ein Level muss nur aus diesen Positionen gut aussehen. Nachteil ist z. B., dass einige Spielmechaniken wie “Fangen spielen” schwerer zu realisieren sind.
  4. Gestural Locomotion: Hiermit meine ich alle Fortbewegungsarten in VR, die durch Nachahmen der entsprechenden Bewegung per Controller umgesetzt werden. Das einfachste Beispiel ist schwimmen durch Gleitzug-Bewegung aus dem Brutschwimmen oder durch den wechselseitigen Armzug aus dem Kraulschwimmen. Etwas innovativer ist die Fortbewegung durch das Schwingen der Arme, wie es Gorilla Tag etabliert hat.

Ein modernes XR Rig unterstützt mindestens zwei der vier genannten Fortbewegungsarten.

Ob der Spieler auf diese Arten ein Abbild seiner selbst, also in der Regel einen Menschen auf zwei Beinen, fortbewegt, ist übrigens ein ganz anderes Thema… in der virtuellen Realität kann man schließlich genau so gut zu einer Katze, einem Raumschiff oder eben einem Gorilla werden.

Interaktion

Wenn wir also in die virtuelle Welt blicken und uns darin bewegen können, wenn auch die Controller oder gar die Hände erfolgreich getracked und dargestellt werden, und wenn wir zu guter letzt auch noch über den Status der verschiedenen Controller Buttons Kenntnis haben oder Handgesten interpretieren können, dann muss es auch möglich sein, mit der Welt zu interagieren.

Dass auf den Körper des virtuellen Spielers in der Regel Gravitation wirkt, haben wir schon früher festgestellt. Der Körper sollte also auch auf andere Objekte in der virtuellen Welt einwirken können, z. B. durch Kollision: Wenn der Spieler gegen eine Wand läuft, wird diese nicht nachgeben. Wenn er aber gegen eine Tür läuft, die halb auf steht, dann öffnet die sich vielleicht weiter und gibt den Weg frei.

Mit den Controllern erwartet der Spieler naturgemäß weitere Interaktionsmöglichkeiten, wie z. B. das Greifen, Bewegen und Werfen von Objekten in unmittelbarer Nähe sowie in der Entfernung (sog. Remote Grab), das Drücken von Tasten und Knöpfen, das Öffnen und Schließen von Türen und Schubladen, das Zeigen auf und Auswählen von UI Elementen, die Auswahl eines Ziels für die Teleportation (siehe oben bei Locomotion) oder das Herauf- oder Herabklettern. Interaktionen mit Objekten gehen oft auch mit haptischem Feedback einher, also dem Vibrieren des Controllers.

Das XR Rig kann das nicht alleine bewerkstelligen – für die Interaktion benötigt es ein Gegenstück, ein Objekt in der Welt, das mit sich interagieren lässt. Aber um solche Interaktionen auslösen zu können bedarf es einiger Bauteile an den Controller-Repräsentationen im Rig.

Noch aufwändiger wird es, wenn anstelle der Controller virtuelle Hände angezeigt werden, bei denen die Fingerhaltung vom Drücken der Grab- und Trigger-Buttons abhängt und selbst die Fingerspitze des ausgestreckten Zeigefingers etwas auslösen kann.

Komfort

Menschen vertragen immersive XR Erlebnisse unterschiedlich gut. Eines der häufigsten Probleme ist die Motion Sickness, die eintritt, weil die visuelle Bewegung nicht mit der physischen Bewegung des Körpers übereinstimmt. Symptome können z. B. Übelkeit, Schwindel oder Desorientierung sein.

Gerade Spiele können diesen Effekt verstärken. Rutschen die dargestellten Bilder pro Sekunde (FPS) in den Keller, weil die aktuell gerenderte Szene besonders anspruchsvoll ist, driften visuelle und physische Erfahrung weiter auseinander und der Körper reagiert stärker. Meta erfordert daher konstante 72 FPS für Apps, die für die breite Öffentlichkeit im Meta Horizon Store veröffentlicht werden sollen.

Das Anbieten von Teleportation als Locomotion-Möglichkeit ist ein Weg, um Motion Sickness zu reduzieren. Eine weitere Maßnahme ist “Snap Turning” oder “Snap Rotation”, d.h. eine stufenweise Rotation um 15 Grad oder mehr, oder die Konfiguration der Drehgeschwindigkeit bei Smooth Turning. Und letztendlich geht all das einher mit einer konfigurierbaren Vignette, die den Sichtbereich (field of vision, FOV) während der Bewegung, Teleportation oder Drehung reduziert. Wer im letzten Teil die XRIT DemoScene angeschaut hat, hat das alles schon in Aktion erlebt.

Da diese Maßnahmen an der Steuerung des Spielers hängen, sind auch sie Teil der Funktionalität, die ein XR Rig mitbringt.

Resümee

Ich hoffe, du hast einen Eindruck davon gewonnen, wie wahnsinnig viel es auf der Anwendungsseite selbst nach all der Magie im Headset noch zu tun gibt. Und wenn du dich jetzt fragst, wie viel dutzend Artikel-Teile es denn dann noch geben muss, bis wir all das erledigt haben, dann lies gleich weiter.

Der Spieler in XR: Das XR Origin Prefab

XR Origin (VR)

XRIT bringt ein paar Helfer mit. Einer davon ist das Anlegen eines fertig konfigurierten XR Camera Rigs und das probieren wir direkt mal aus. Klicke mit rechts in einen freien Bereich der Hierarchy und wähle XR → XR Origin (XR Rig). Das Camera Rig wird dann in der Szene platziert. Bitte stelle sicher, dass es auch am Ursprung (0, 0, 0) positioniert ist.

Neben dem Camera Rig ist noch ein weiteres Objekt, XR Interaction Manager, hinzugekommen, das wir vorerst ignorieren.

Wenn du die Anwendung jetzt starten würdest, würdest du in der Mitte der Ebene stehen und könntest dich umsehen. Aber da die Szene noch so leer ist und es keine weiteren Orientierungspunkte gibt, ist das unspektakulär. Lass uns also zumindest noch einen Würfel in die Szene stellen, der uns auch später als Tisch dienen kann.

Klicke wieder auf einen freie Stelle in der Hierarchy und wähle 3D Object → Cube. Ändere dann im Inspector die Position des Cubes auf (0, 0, 3).

Bevor du gleich das “Spiel” startest, ein kurzer Hinweis: ich arbeite noch mit einer Preview Version von Unity 6 und hier sind gelegentliche Fehler noch zu erwarten. Ein Fehler, der mir begegnet ist, ist, dass meine nicht gespeicherten Änderungen in einer Szene nach einem Build komplett verloren gehen. Und ob ich Änderungen speichern möchte, werde ich auch nicht gefragt. Ich versuche also, vor jedem Build einmal von Hand zu speichern. Ich hoffe, in der Release Version ist dieser Fehler behoben… Ein anderer Fehler ist, dass “Build and Run” gelegentlich ohne Fehlermeldung stoppt und die Anwendung nicht transferiert und gestartet wird. Hier hilft dann nur ein Unity 6 Neustart.

Wenn du jetzt startest, sieht das Ganze so aus:

Die bescheidene Beleuchtung und die merkwürdig aussehenden Schatten werden wir später bearbeiten. Für den Moment ist wichtiger, dass dieses angelegte Rig nur die Kameraposition steuert. Bewegen oder Umdrehen kann man sich damit noch nicht und von Controllern fehlt auch noch jede Spur.

Schauen wir uns das angelegte “XR Origin (VR)” GameObject und seine Child Objects einmal genauer an. Ich habe dazu Hierarchy und Inspector Views nebeneinander gelegt:

Das “XR Origin (VR)” Objekt ist die Repräsentation des Nutzers in VR, wie wir sie gerade angelegt haben. Es enthält zwei Komponenten:

XR Origin fasst ein paar wichtige Informationen zusammen:

  • Das “Origin Base GameObject” entspricht der Spielerposition und ist auch das Objekt, was später per Locomotion bewegt würde. Aufgrund der einfachen Struktur dieses Objekts zeigt es auf sich selbst: das “XR Origin (VR)” GameObject würde sich bewegen.
  • Das “Camera Floor Offset GameObject” stellt den vertikalen Versatz zwischen der Spielerposition in der Welt (XR Origin) und der Kamera dar.
  • Die “Camera” ist dann die eigentliche Unity Camera. Das GameObject ist vom “Camera Offset GameObject” separiert, da die Kamera ja, wie du von oben weißt, eine eigene Pose ausgehend von dem Offset haben kann.
  • Der “Tracking Origin Mode” legt fest, auf welche Weise das Offset bestimmt werden soll. “Not Specified” bedeutet, dass der Standard des Geräts verwendet werden soll, auf dem die Anwendung letztendlich läuft. Auf der Quest wäre das “Floor”.
  • Das “Camera Y Offset” ist relevant, wenn “Device” verwendet wird. In diesem Fall wird das Child Object “Camera Offset” automatisch auf diese Höhe gesetzt.

Der Input Action Manager erlaubt, mehrere InputActionAssets aus dem neuen Input System zusammenzufassen. Diese Input Actions werden dann synchron mit dem XR Origin GameObject aktiviert oder deaktiviert.

Unity’s Input System ist nicht Inhalt dieses Artikels, daher nur ganz kurz zur Erinnerung: in den InputActionAssets werden Aktionen des Spiels auf Controller-Eingaben gemappt. Im Spiel können wir dann z. B. den Zustand der “Grip” Aktion abfragen ohne zu wissen, ob sich dahinter tatsächlich ein physikalischer Controller-Button verbirgt oder vielleicht eine Emulation.

Hier ist ein Input Action Asset vorkonfiguriert: “XRI Default Input Actions”. Wenn du darauf klickst, wirst du feststellen, dass das eine Datei in den Starter Assets des XRIT ist. Durch Klick auf “Edit Asset” im Inspector kannst du dir genauer anschauen, was dort definiert ist. Wichtig für später ist eine Sache: die Action Maps beginnen alle mit XRI, z. B. “XRI Head”, und darin gibt es dann Actions wie “Position” und “Rotation”. Wir werden gleich auf dieses Mapping zurückkommen.

Wir gehen aber zuerst wieder zurück zur Objekthierarchie des XR Rigs. Das “Camera Offset” Child Object ist vergleichsweise einfach:

Es enthält keine weiteren Komponenten und ist wirklich ausschließlich für den Höhenversatz der Kamera zuständig. Die XR Origin Komponente aus dem Parent GO setzt den “y” Wert der Position bei Bedarf.

Richtig interessant ist die “Main Camera”:

Hier finden sich zunächst die “Camera” und “Audio Listener” Komponenten. Da diese sich nicht von einer “Flat Screen”-Anwendung unterscheiden, gehe ich nicht weiter auf Details ein. Ich ignoriere auch “Universal Additional Camera Data”, weil diese Komponente zur Rendering Pipeline gehört und automatisch hinzugefügt wurde.

Spannend ist die Tracked Pose Driver (Input System) Komponente, die offensichtlich, wie der Name sagt, nicht aus der XR Unterstützung kommt, sondern aus dem Input System.

  • Der “Tracking Type” legt fest, was eigentlich getracked werden soll: nur Position, nur Rotation, oder beides. Bei der Kamera macht natürlich beides Sinn.
  • Der “Update Type” sagt, zu welchem Zeitpunkt die Informationen in das GameObject übertragen werden sollen. Im “Update” Loop, vorm Rendern, oder beides. Da Update und Render auseinanderlaufen können ist “Update And Before Render” die beste Option für VR, um die Darstellung synchron zu halten und es dem Spieler so angenehm wie möglich zu machen.
  • Der “Tracking State Input” liefert ein boolean das besagt, ob das Headset gerade gültige Werte liefert oder nicht. Das kann relevant sein, wenn der Spieler die Boundary verlässt. “Ignore Tracking State” sagt, ob diese Information verarbeitet werden soll oder nicht.
  • “Position Input” und “Rotation Input” bindet die anzuwendenden Positions- und Rotations-Werte an bestimmte Eingabequellen (Actions).

Anmerkung: Mit unserem XRIT Sample haben wir auch ein komplett konfiguriertes InputActionAsset, das wir vorhin schon kurz besprochen haben. Ich persönlich finde es einfacher, die jeweiligen Action Map Indirektionen für “Position Input” und “Rotation Input” zu verwenden, anstatt alle Actions manuell zu verdrahten. Ich empfehle dir daher, für “Position Input” und “Rotation Input” durch Klick auf die drei Pünktchen von “Use Actions” zu “Use References” zu wechseln. Dann kann man die XRI* Action Maps verwenden, die wir vorhin kurz beim Betrachten der Input Action Manager Komponente besprochen haben: XRI Head/Position und XRI Head/Rotation wären die entsprechenden Referenzen.

Nach dieser Betrachtung des XR Origin (VR) GameObjects sehen wir also, dass es tatsächlich nur die Orientierung des Kopfes/Headsets auswertet, auf die Kamera anwendet und nichts anderes kann. Müssen wir Controller-Support und Locomotion also selbst implementieren?

Die Antwort ist nein, aber bevor wir mit der Lösung das Kapitel abschließen, wagen wir noch ein Experiment.

Controller Support

Wenn die Kamera also lediglich durch eine Tracked Pose Driver Komponente gesteuert wird, die Eingabedaten des Headsets verarbeitet, können wir dann nicht auf dem gleichen Weg eigene Controller bauen? Ja, können wir!

Im Grundlagenteil haben wir besprochen, dass Controller und Kamera unabhängig voneinander am Ursprung hängen. Wir können also mal probieren, einen kleinen Würfel als Child von “Camera Offset” anzulegen. Klicke rechts auf das “Camera Offset” Objekt in der Hierarchy und dann 3D Object → Cube. Der ist standardmäßig etwas groß, so dass wir die Scale auf (0.2 / 0.2 / 0.2) reduzieren. Den Box Collider brauchen wir im Moment nicht, wir können ihn durch Rechtsklick auf den Titel gefolgt von “Remove Component” entfernen.

Jetzt können wir im Inspector durch Klick auf “Add Component” die “Tracked Pose Driver (Input System)” Komponente hinzufügen.

Letztendlich müssen wir nur noch konfigurieren, woher dieses Objekt seine Positions- und Rotations-Informationen beziehen soll. Ich wechsele dazu durch Klick auf die drei Punkte neben “Position Input” und “Rotation Input” wieder jeweils zu “Use Reference” und lege dann jeweils “XRI Right/Position” und “XRI Right/Rotation” als Wert fest:

Den “Tracking State Input” lasse ich für diesen Test außen vor.

Wenn wir die Anwendung jetzt starten, wird dieser neue Würfel gemäß der Controller-Position des rechten Controllers bewegt und rotiert:

Wenn du Lust hast, kannst du den Würfel duplizieren und im Duplikat die linken Controller-Actions verdrahten.

In früheren XRIT Versionen war das genau der Weg, wie sich Entwickler ihre XR Rigs zusammengeklickt haben. Heute bringt das XRIT Sample Project zum Glück ein komplett konfiguriertes Prefab mit.

XR Origin (XR Rig)

Ich werde nicht müde zu erwähnen, wie viel Arbeit schon in XRIT geflossen ist, und ich bin dankbar dafür, dass wir von den Entwicklern im Sample Project auch ein fertig konfiguriertes XR Rig mit Controller-Support und Locomotion bekommen haben. Damit tauschen wir nun unsere bescheidenen eigenen Versuche aus.

Du kannst sowohl das “XR Origin (VR)” GameObject als auch den automatisch eingefügten “XR Interaction Manager” aus der Szene löschen.

Dann wählst du im Project View das “XR Origin (XR Rig)” Prefab aus dem Ordner Assets → Samples → XR Interaction Toolkit → 3.0.5 → Starter Assets → Prefabs und ziehst es in die Hierarchy.

Die Vorschau des Prefabs mit der Controller-Grafik lässt schon erahnen, dass wir hier mehr Funktionalität bekommen, als mit dem vorherigen “XR Origin (VR)” Objekt. Und tatsächlich, wenn wir das Objekt in der Szene mal aufklappen, finden wir wesentlich mehr Child Objects, an denen verschiedene Komponenten hängen:

Wir werden uns diese Bauteile nach Bedarf im Detail ansehen. Jetzt probieren wir aber das neue XR Rig nochmal im Headset aus!

Gleichen wir einmal das, was wir hier sehen, mit dem zuvor besprochenen ab:

  • Standardmäßig ist offenbar Smooth Locomotion per linkem Thumbstick aktiviert.
  • Die Drehung erfolgt per linkem Thumbstick in großzügigen Schritten.
  • Keine der Controller-Tasten (X/Y/A/B) scheint belegt zu sein.
  • Man sieht aber, dass die Trigger- oder Grip-Tastendrücke zumindest verarbeitet und angezeigt werden.
  • Es wird keine Vignette angezeigt.
  • Ich kann die Plattform verlassen und falle in die Tiefe.
  • Wenn ich, während der Trigger rechts gedrückt ist, den rechten Thumbstick nach vorne schiebe, aktiviere ich Teleportation. Es gibt allerdings kein Ziel, weshalb der Teleportation-Ray rot bleibt. (Das habe ich im Video leider vergessen.)

Damit haben wir eine gute Grundlage für unseren virtuellen Spieler!

Bevor wir das Kapitel schließen, will ich aber noch zeigen, wie man die Vignette und Teleportation aktivieren bzw. Snap Turning deaktiveren kann. Wir haben ja noch kein schickes Einstellungen-Menü. So kannst du dir das Rig für’s weitere Testen so konfigurieren, wie es dir selbst am besten bekommt.

Vignette

Die Vignette ist ein separates Prefab, das an die Kamera gehängt werden muss. Öffne die Main Camera im Rig in der Hierarchy. Suche dann im Project View den Ordner “Tunneling Vignette” unter Assets → Samples → XR Interaction Toolkit → 3.0.5 → Starter Assets. Im Ordner findest du ein Prefab “Tunneling Vignette” (erkennbar an der blauen Box als Icon). Ziehe dieses Prefab auf deine Main Camera, damit es als Child platziert wird.

Damit die Vignette aktiviert wird, benötigt sie Informationen von den verschiedenen Locomotion-Komponenten. Diese müssen über das “Locomotion Vignette Providers” Attribut verknüpft werden. Öffne die “Locomotion” GameObject Hierarchie, so dass die Child-GOs Turn, Move, Grab Move, Teleportation und Climb sichtbar werden. Falls du dabei versehentlich eines der GameObjects auswählst, wähle danach wieder die gerade hinzugefügte “Tunneling Vignette” aus, so dass du im Inspector die “Locomotion Vignette Providers” siehst.

Schaffe nun durch Klick auf das Plus-Symbol unterhalb “Locomotion Vignette Providers” sechs freie Slots, um dort die Locomotion-Methoden hineinzuziehen. Falls du dich jetzt fragst, warum wir sechs Slots anlegen, wenn es doch nur fünf Child-GameObjects gibt (Turn, Move, Grab Move, Teleportation, Climb), dann hast du richtig gut aufgepasst! Die Antwort ist, dass auf dem “Turn” GameObject tatsächlich zwei Provider existieren: ein Snap Turn Provider und ein Continuous Turn Provider. Wenn du das GameObject in einen Slot ziehst, erscheint rechts daneben ein Dropdown, wo du die entsprechende Komponente auswählen kannst.

So sollte das am Ende aussehen:

Wenn du das Spiel jetzt startest, wirst du feststellen, dass bei Bewegung oder Snap Turn die schwarze Vignette einblendet.

Wenn du im Inspector auf der Tunneling Vignette die “Default Parameters” aufklappst, kannst du die Vignette nach deinen Bedürfnissen anpassen.

Smooth Turn aktivieren

Die Smooth Turn und Snap Turn Locomotion Provider befinden sich im Locomotion/Turn GameObject, aber die Orchestrierung findet in den Controllern statt. Wenn du also z. B. Smooth Turning mit dem rechten Controller aktivieren willst, öffne das Right Controller GameObject im Rig und aktiviere dort im Inspector “Smooth Turn Enabled”:

Teleportation aktivieren

Um dich auf unserer Fläche per Teleportation fortzubewegen, musst du aus der Fläche eine “Teleportation Area” machen. Dazu kannst du die Komponente mit dem gleichen Namen an die Ebene in der Szene hängen:

Das alleine reicht allerdings noch nicht. Zum einen muss noch die “Interaction Layer Mask” von “Default” auf “Teleport” geändert werden. Dazu musst du in der Auswahl erst “Nothing” auswählen und dann “Teleport”. Zum anderen erwartet die Teleportation Area eine Liste von Colliders, die sie als Teleportationsziele verwenden kann. Ziehe daher das Plane GameObject aus der Hierarchy auf den “Colliders” Label der Teleportation Area Komponente:

Jetzt kannst du dich mit rechtem Trigger und rechtem Thumbstick nach vorne auf der Fläche teleportieren – nicht allerdings auf den Cube, den wir zusätzlich in die Szene platziert haben.

Ausblick

Im nächsten Teil machen wir uns das neue Rig zunutze und interagieren mit der Welt.

Leave a Reply

Your email address will not be published. Required fields are marked *