Wie man mit C# und Unity die virtuelle Welt erobert

Entwicklung für Windows Mixed Reality
Keine Kommentare

Auch nach zwei Jahren ist das Interesse an der HoloLens ungebrochen, und die ersten Windows-Mixed-Reality-Geräte von Drittherstellern werden gerade veröffentlicht. Es ist ganz klar: Die Themen Hologramme und Mixed Reality sind gekommen, um zu bleiben. Für C#-Entwickler ist jetzt ein fantastischer Zeitpunkt, um sich mit dieser neuen Technologie zu beschäftigen.

Bevor man mit der Entwicklung für diese neue Technologie beginnt, muss man verstehen, dass man nicht Programme für die HoloLens entwickelt, sondern Apps für Windows Mixed Reality. Windows Mixed Reality ist ein spezielles Betriebssystem von Microsoft auf Basis von Windows 10 mit Fokus auf die Darstellung von virtuellen Inhalten, sei es Mixed Reality oder Virtual Reality. Die HoloLens ist lediglich das erste veröffentlichte Gerät für dieses Betriebssystem. Dritthersteller, allen voran Acer und HP, veröffentlichen gerade eigene Geräte, die mit Windows Mixed Reality betrieben werden.

Alle Anwendungen für Windows Mixed Reality sind Windows-Universal-Platform-Apps (UWP-Apps). Das können zum einen speziell für Windows Mixed Reality entwickelte Apps mit 3-D-Inhalten sein, zum anderen aber auch allgemeine Windows-10-UWP-Apps, die auch auf jedem Windows-10-PC oder -Laptop laufen. Während die speziellen 3-D-Apps in einem 3-D-Modus ihre Inhalte darstellen, werden die allgemeinen UWP-Apps als flache 2-D-Fenster dargestellt, die man beliebig im Raum verteilen und benutzen kann.

Werkzeuge und Entwicklungsumgebung

Microsoft ist mit Unity eine Partnerschaft eingegangen, um das Entwickeln von Mixed-Reality-Apps möglichst einfach zu halten. Unity ist eine umfangreiche Plattform zur Entwicklung von Computerspielen und umfasst unter anderem eine Spiele-Engine sowie eine eingängige Entwicklungsumgebung. Programmcode wird wahlweise in C# oder JavaScript geschrieben. Unity ist keine neue Plattform, sondern ist seit 2004 am Markt etabliert und wird von einer aktiven Community aus Spieleentwicklern genutzt. Neben den Entwicklerwerkzeugen beinhaltet Unity einen Marktplatz für Assets wie Scripts, Texturen, Shader, Animation und ganze 3-D-Modelle, die teils kostenfrei und teils gegen ein Entgelt in eigenen Programmen genutzt werden können. Von alldem profitieren Windows-Mixed-Reality-Entwickler, wenn sie für die Entwicklung der Holographic-Apps Unity einsetzen. Es gibt neben Unity auch andere Möglichkeiten, Holographic-Apps zu entwickeln. Da die Verwendung von Unity aber am anfängerfreundlichsten ist, beschränkt sich dieser Artikel darauf.

Um mit der Entwicklung beginnen zu können, werden einige Programme und SDKs benötigt. Auf dem Entwicklercomputer sollte die aktuellste Version von Windows 10 installiert sein. Es wird eine Variante von Visual Studio 2017 sowie die Unity-Entwicklungsumgebung benötigt. Im Artikel werden die Programme in englischer Sprache genutzt. Empfehlenswert ist außerdem der HoloLens-Emulator inklusive der Holographic-Templates für Visual Studio. Wichtig: Hyper-V wird benötigt, um den Emulator auszuführen. Natürlich kann man stattdessen auch direkt auf einem Windows-Mixed-Reality-Gerät debuggen, wenn man eins besitzt.

Weiterhin wird das Microsoft HoloToolkit für Unity benötigt. Das HoloToolkit ist eine Sammlung von Assets, Scripts und Einstellungen für Mixed-Reality-Projekte. Es ist Open Source und wird über ein GitHub Repository zur Verfügung gestellt. Für den Artikel wird nur das eigentliche Toolkit mit einer Bezeichnung analog zu HoloToolkit-Unity-<versionsnummer>.unitypackage benötigt. Das Examples-Paket und das Testpaket müssen nicht heruntergeladen werden.

Werkzeuge und Entwicklungsumgebung

Im Laufe des Artikels soll eine Windows-Mixed-Reality-Anwendung entstehen, in der mit einem Air Tap – einer Handgeste des Nutzers, die einem Klick entspricht – ein Ball vom Nutzer weg in den Raum geschossen wird und physikalisch korrekt an der Umgebung abprallt. Dazu muss zuallererst ein neues Projekt in Unity erstellt und geöffnet werden.

Abb. 1: Das leere Projekt

Abb. 1: Das leere Projekt

Die Unity-Umgebung sollte standardgemäß, wie in Abbildung 1 gezeigt, aussehen. Eine kurze Übersicht über die einzelnen Fenster:

  • Oben befindet sich die Menüleiste sowie diverse Werkzeuge, um den 3-D-Szeneneditor zu bedienen.
  • Mittig unter der Menüleiste befindet sich der 3-D-Editor für die aktuelle Szene.
  • Am linken Rand ist das Szenenmenü mit der aktuell geöffneten Szene und allen darin enthaltenen 3-D-Objekten aufgebaut.
  • Links unten befindet sich das Projektmenü mit allen importierten Assets und Paketen.
  • Die rechte Seite nimmt der Inspector ein, mit dem man markierte Komponenten konfiguriert kann.

Nachdem das Projekt erstellt und geöffnet wurde, sollte man das HoloToolkit importieren. Das geschieht über die Importfunktion für Assets-Pakete in der Menüleiste unter ASSETS > IMPORT PACKAGE > CUSTOM PACKAGE.

In einem Importdialog können zu importierende Komponenten aus dem Asset-Paket ausgewählt werden. Der Einfachheit halber kann man erst einmal das vollständige HoloToolkit-Paket importieren. Nicht benötigte Teile können zum Schluss wieder entfernt werden. Gerade bei großen Paketen ist es aber durchaus sinnvoll, von vornherein nur die Teile zu importieren, die wirklich benötigt werden, um das Projekt klein zu halten.

Nachdem das HoloToolkit importiert wurde, kann über den neuen Eintrag HOLOTOOLKIT > CONFIGURE in der Menüleiste mit wenigen Klicks das Projekt für Windows Mixed Reality konfiguriert werden.

Die Option APPLY HOLOLENS SCENE SETTINGS konfiguriert die aktuelle Szene mit verschiedenen Kamera- und Rendereinstellungen. Wenn man weitere Szenen erstellen möchte, sollte man diese Konfiguration auf jeder Szene ausführen.

Die Option APPLY HOLOLENS PROJECT SETTINGS passt Einstellungen auf Projekteben an. Das Projekt wird dadurch unter anderem als Windows-Universal-Platform-App eingerichtet und für Virtual Reality konfiguriert.

Wie auch bei mobilen Apps üblich, sind hier bestimmte Funktionen der Plattform nur verfügbar, wenn man den Zugriff explizit einrichtet. So wie eine Smartphone-App Zugriff auf GPS und Internet bekommen muss, muss der Zugriff auf die Kamera, das Mikrofon, Internet und Spatial Perception bei Mixed-Reality-Apps erlaubt werden. Unter APPLY HOLOLENS CAPABILITY SETTINGS kann genau das eingerichtet werden.

Für den Artikel wird Spatial Perception benötigt. Ohne die Erlaubnis, Spatial Perception nutzen zu können, kann die App nicht auf die Umgebungsdaten des Geräts zugreifen und weiß somit nicht, wo Hindernisse im Raum sind und wo der Raum aufhört (Abb. 2). Diese Informationen werden aber benötigt, wenn der virtuelle Ball von echten Objekten abprallen soll.

Abb. 2: Ein Raumscan [3]

Abb. 2: Ein Raumscan

Einrichten der Szene

Eine Szene in Unity ist eine geschlossene Umgebung, in der Objekte dargestellt werden. Ein Projekt kann eine oder mehrere Szenen beinhalten und es kann zur Laufzeit zwischen Szenen gewechselt werden. Für dieses Projekt wird nur eine einzelne Szene benötigt. Beim Öffnen des Projekts wurde bereits eine leere Szene angelegt. Diese wurde bisher aber nicht gespeichert und befindet sich deshalb nur im Arbeitsspeicher. Über FILE > SAVE SCENE oder STRG + S kann man die Szene benennen und im Projektmenü speichern. Um das Projekt übersichtlich zu halten, empfiehlt es sich, für die Szenen einen eigenen Unterordner anzulegen. Am einfachsten geht das direkt über das Projektmenü, indem man über einen Rechtsklick auf das Assets-Verzeichnis über CREATE > FOLDER einen Szenenordner anlegt.

In der Szene wurden von Unity bereits zwei Objekte angelegt: eine Kamera und ein Licht. Das Licht, ein Directional Light, beleuchtet alle Objekte in der Szene aus einem bestimmten Winkel. Für dieses Projekt ist das in Ordnung.

Die Kamera ist das virtuelle Auge des Nutzers. Im Fall von Mixed-Reality-Anwendungen ist die Kamera der Kopf des Nutzers. Was sich im Blickfeld der Kamera befindet, wird dem Nutzer angezeigt. Gesteuert wird die Kamera vom Nutzer.

Die Standardkamera ist für den Einsatz in einer Mixed-Reality-Umgebung nicht korrekt konfiguriert. Praktischerweise beinhaltet das HoloToolkit eine vorkonfigurierte HoloLens-Kamera. Über das Suchenfeld im Projektmenü kann man das importierte Toolkit schnell nach der Komponente „HoloLensCamera“ durchsuchen und diese per Drag and Drop in die Szene ziehen. Die Standardkamera wird nicht mehr benötigt und sollte gelöscht werden.

 

API Conference 2018

API Management – was braucht man um erfolgreich zu sein?

mit Andre Karalus und Carsten Sensler (ArtOfArc)

Web APIs mit Node.js entwickeln

mit Sebastian Springer (MaibornWolff GmbH)

Neben der Kamera werden einige Scripts benötigt, um einen Air Tap verarbeiten zu können und um die virtuelle Umgebung anzuzeigen. Grundsätzlich können Scripts an beliebige Objekte in der Szene angehängt werden, beispielsweise die Kamera oder das Licht. Um die Scripts aber später wiederzufinden, sollte man sie ordentlich verwalten. Für allgemeine Managementscripte bietet es sich daher an, diese alle in einem Managementobjekt zu sammeln. Mit einem Rechtsklick in die Szene kann ein Menü zum Hinzufügen von Objekten geöffnet werden. Die Option Create Empty erzeugt einen funktionslosen und unsichtbaren Container – genau richtig, um alle ManagementScripts an einem Ort zu bündeln, den Rest der Szene aber dadurch nicht weiter zu beeinflussen.

Aus dem HoloToolkit werden die Komponenten InputManager, Spatial Mapping Observer sowie Spatial Mapping Manager benötigt. Die Komponenten können wieder über den Projektbrowser gesucht und anschließend via Drag and Drop auf das Managerobjekt in der Szene gezogen werden. Der InputManager verarbeitet, wie der Name vermuten lässt, die Nutzereingaben. Der Spatial Mapping Observer verarbeitet die gescannte Umgebung und reagiert auf ihre Änderungen. Der Spatial Mapping Manager visualisiert den Raumscan mit einem beliebigen Material.

Das Anzeigen des Raumscans muss auf dem Spatial Mapping Manager explizit aktiviert werden. Ein Klick auf das Managerobjekt öffnet den Inspector, in dem alle Komponenten des Objekts angezeigt werden, unter anderem der Spatial Mapping Manager. Die Option Draw Visual Mesh beim Spatial Mapping Manager sorgt dafür, dass der Raumscan angezeigt wird. Um den Raumscan anzuzeigen, sollte diese Option aktiviert werden (Abb. 3).

Die Visualisierung des Raumscans benötigt ein Material. Ein Material ist ein Bündel aus Textur, Shadern und Farben, die bestimmen, wie Oberflächen aussehen. Das Material für die Oberfläche des Raumscans wird über die Option Surface Material ausgewählt. Beim Klick öffnet sich ein Drop-down, über das das Projekt nach Materialien durchsucht werden kann. Das HoloToolkit liefert das Material SpatialMappingSurface mit, mit dem der Raumscan als Gittermuster visualisiert werden kann. Beliebige andere Materialien funktionieren natürlich auch.

Abb. 3: Scripts auf dem Managerobjekt

Abb. 3: Scripts auf dem Managerobjekt

Das Ball-Script

Es fehlt noch das Script, mit dem Objekte in den Raum geschossen werden können. Über den ADD COMPONENT-Button im Inspector des Managerobjekts können nicht nur bestehende Komponenten hinzugefügt, sondern auch neue Elemente erstellt und verknüpft werden. Für dieses Projekt wird ein neues Script benötigt, das man über das Menü ADD COMPONENTS > NEW SCRIPT erstellen kann. Die Sprache des Scripts ist C#.

Das neu erstellte Script wird auf der Hauptebene im Projektmenü abgelegt. Das Script kann jederzeit an eine andere Stelle verschoben werden, wenn es auf der Hauptebene stört. Ein Doppelklick auf das Script öffnet dieses in Visual Studio. Das Script ist bis auf die zwei Methodenrümpfe Start und Update leer und erbt von MonoBehaviour.

MonoBehaviour ist die Basisklasse für alle C# Scripts, die direkt mit Unity interagieren sollen. Es gibt außer Start und Update noch einige andere Methoden, die von Unity zur Laufzeit aufgerufen werden, wenn sie vorhanden sind. Beispielsweise wird die Start-Methode aufgerufen, wenn das Objekt, das das Script beinhaltet, instanziiert wird, und die Update-Methode bei jedem Frame-Update, zu dem das Objekt existiert.

Das Ball-Script muss beim Start des Managerobjekts einen Listener registrieren, um Air Taps vom Nutzer zu registrieren, damit jeweils ein neues Objekt vor dem Nutzer erzeugt und verschossen werden kann (Listing 1). Die Updatemethode wird dafür nicht benötigt und kann gelöscht werden.

{
  // Unity-bearbeitbares Property für das zu verschießende Objekt
  public GameObject Prefab;
  // Unity-bearbeitbares Property für die maximale Anzahl an aktiven Objekten
  public int MaxNumberOfObjects;

  private GestureRecognizer _gestureRecognizer;
  // Cache für aktiv erzeugte Objekte
  private List<UnityEngine.Object> _launchedGameObjects = new List<UnityEngine.Object>();

  private void OnTap(InteractionSourceKind source, int tapCount, Ray headRay)
  {
    if (Prefab == null || MaxNumberOfObjects < 1)
    {
      return;
    }

    var prefabInstance = LaunchPrefab();
    _launchedGameObjects.Add(prefabInstance);
    Cleanup();
  }

  // Löscht alte Objekte, wenn maximale Anzahl überschritten wurde
  private void Cleanup()
  {
    while (_launchedGameObjects.Count > MaxNumberOfObjects)
    {
      var old = _launchedGameObjects.First();
      _launchedGameObjects.RemoveAt(0);
      Destroy(old);
    }
  }

  // Instanziiert ein GameObjekt aus dem Prefab und verschießt es
  private UnityEngine.Object LaunchPrefab()
  {
    var cameraPosition = Camera.main.transform.position;
    var cameraRotation = Camera.main.transform.rotation;

    // Berechnet Position 1 Meter vor Nutzer
    var prefabPosition = cameraPosition + Camera.main.transform.forward * 1.0f;

    var instance = Instantiate(Prefab, prefabPosition, cameraRotation);

    if (instance is GameObject)
    {
      var gameObject = (instance as GameObject);
      var rigidBody = gameObject.GetComponent<Rigidbody>();
      if (rigidBody == null)
      {
        rigidBody = gameObject.AddComponent<Rigidbody>();
      }
      rigidBody.useGravity = true;
      rigidBody.AddForce(Camera.main.transform.forward * 10.0f, ForceMode.Impulse);
    }

    return instance;
  }

  void Start()
  {
    _gestureRecognizer = new GestureRecognizer();
    _gestureRecognizer.TappedEvent += OnTap;
    _gestureRecognizer.StartCapturingGestures();
  }
}

Die Startmethode instanziiert und startet einen GestureRecognizer und registriert eine Methode für das Erkennen von Air Taps. Die OnTap-Methode ist das Herz dieses Scripts. In der Methode wird ein neues Objekt aus einer Referenz erzeugt, losgeschossen und zur Verwaltung gespeichert. Damit die Anwendung nicht irgendwann wegen zu vielen aktiven Objekten langsam wird, empfiehlt es sich, die erzeugten Objekte auf eine bestimmte Anzahl zu begrenzen und die ältesten Objekte zu entfernen, wenn mehr neue Objekte erzeugt werden. Dieser Check wird am Ende der OnTap-Methode durchgeführt.

Um den Objekttyp und die maximale Anzahl an Objekten dynamischer zu gestalten, werden diese nicht fest im Script einprogrammiert, sondern über die Properties Prefab und MaxNumberOfObjects editierbar gemacht. Damit eine Option im Inspector in Unity angezeigt wird – so wie beispielsweise das Material beim Spatial Mapping Manager – muss lediglich eine Public Property erzeugt werden.

Die LaunchPrefab-Methode erfüllt zwei Aufgaben. Zum einen stellt sie sicher, dass das neue Objekt eine Unity-Komponente vom Typ Rigidbody hat, und zum anderen gibt sie dem Objekt einen Stoß, damit es von der Kamera weggeschossen wird. Die Komponente Rigidbody sorgt dafür, dass Objekte physikalisch korrekt fallen und auf die Kollision mit anderen Objekten reagieren können. Würde dem neu erstellen Objekt diese Komponente fehlen, würde es nur bewegungslos kurz vor dem Nutzer in der Luft schweben.

Im Anschluss wird die Komponente via Option useGravity so konfiguriert, dass sie nach unten fällt, und bekommt einen initialen Impuls über die Methode AddForce, um vom Nutzer weg gestoßen zu werden.

Was ist ein Prefab?

Ein Prefab ist ein vorkonfiguriertes Asset, das von einem Script oder im Editor als Vorlage zum Erzeugen von Objekten genutzt werden kann. Jedes Objekt, das man in einer Szene erstellt, kann als Prefab abgespeichert und anschließend wiederverwendet werden.

Das ShootPrefab-Script hat die öffentliche Property Prefab vom Typ GameObjekt. Jedes als Prefab gespeicherte Asset kann im Unity-Editor über diese Property mit dem Script verknüpft werden. Da das Projekt „BallSpiel“ heißt, wird im Folgenden ein Ball-Prefab erstellt. Über den Dialog zum Hinzufügen von neuen 3-D-Objekten wird in der Szene eine Sphere hinzugefügt (Abb. 4). Die Standard-Sphere ist 1 Meter hoch, breit und tief. Es empfiehlt sich, das Objekt etwas zu verkleinern.

Abb. 4: Sphere hinzufügen

Abb. 4: Sphere hinzufügen

Über den Inspector kann in der Kategorie TRANSFORM beim Punkt Scale das Objekt skaliert werden. Der Wert 0.25 für Höhe, Breite und Tiefe eignet sich gut für diesen Anwendungsfall.

Aus der Sphere in der Szene wird als Nächstes ein Prefab erzeugt. Dazu zieht man das Sphere-Objekt einfach in das Assets-Verzeichnis. Das führt dazu, dass ein Sphere Prefab mit den gerade getätigten Einstellungen erstellt wird.

Kompilieren und ausprobieren

Das Projekt ist fast abgeschlossen. Das ShootPrefab-Script muss auf das Managers-Objekt gezogen und die beiden Optionen Prefab und Max Number Of Objects müssen ausgefüllt werden. Als Prefab wird der gerade erstellte Ball genutzt. Via Drag and Drop aus dem Projektmenü oder via HINZUFÜGEN-Dialog rechts vom Feld kann es mit dem Script verknüpft werden. Das Feld Max Number Of Objects muss mit einer positiven Zahl gefüllt werden, um die maximale Anzahl an Objekten zu begrenzen – für den Moment sollten 20 ausreichen sein.

Es bleibt, das Projekt zu bauen und auf dem HoloLens-Emulator oder einem echten Gerät auszuführen. Das HoloToolkit hat unter anderem ein Hilfsmenü zum Bauen und Öffnen des Projekts in Unity installiert. Zu finden ist es im Menü unter HOLOTOOLKIT > BUILD WINDOW (Abb. 5).

Abb. 5: Ausschnitt aus dem HoloToolkit Build Window

Abb. 5: Ausschnitt aus dem HoloToolkit Build Window

Ein Klick auf BUILD VISUAL STUDIO SLN erstellt das Projekt als Visual Studio Solution. Anschließend kann es über Open SLN in Visual Studio geöffnet werden.

Im Visual Studio steht die Option, für den HoloLens-Emulator zu kompilieren, nur zur Verfügung, wenn die Plattform auf x86 oder x64 eingestellt ist. Wichtig: Hyper-V muss aktiv sein.

Ein Klick auf den Play-Button startet den HoloLens-Emulator, kompiliert das Projekt, installiert es auf dem virtuellen Gerät und führt es anschließend aus.

Wenn alles funktioniert, wird nach dem App-Start ein mit einem weißen Gittermuster visualisierter Raumscan sichtbar, in dem man sich mit W, A, S und D vor, nach links, zurück und nach rechts bewegen und mit der rechten Maustaste Bälle verschießen kann (Abb. 6).

Abb. 6: Das Ballspiel in Aktion

Abb. 6: Das Ballspiel in Aktion

Nächste Schritte

Der Einstieg in die Entwicklung für Windows Mixed Reality mit Unity ist geschafft. Nun gibt es viele Möglichkeiten, das bestehende Projekt zu erweitern. Naheliegend ist beispielsweise, Prefabs bei der Kollision mit dem Raumscan oder anderen Objekten ein Geräusch abspielen zu lassen, virtuelle Hindernisse im Raum zu platzieren, oder das Prefab-Script zu erweitern, sodass man verschossene Objekte aufheben und erneut verschießen kann.

Wenn einem Unity nicht zusagt, kann man sich auch mit anderen Technologien zum Erstellen von Mixed-Reality-Apps beschäftigen. Für Entwickler mit Erfahrung in DirectX ist SharpDX eine gute Alternative. Eine andere Option ist UrhoSharp, ein C#-Wrapper für die Urho3D Engine.

Nach den ersten Gehversuchen stehen einem jetzt alle Türen in der Entwicklung für Windows Mixed Reality offen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -