Erschließung neuer Use Cases und Mehrwerte mit Unity – Teil 3

User Interface und Deployment in Unity

User Interface und Deployment in Unity

Erschließung neuer Use Cases und Mehrwerte mit Unity – Teil 3

User Interface und Deployment in Unity


In 3D-Programmen interagiert der Anwender viel mit der 3D-Welt. Zur weiteren Informationsdarstellung benötigt es jedoch auch ein User Interface, das entweder dediziert dem Anwender zur Verfügung gestellt wird oder ein integraler Bestandteil der 3D-Welt selbst ist. Und das beste User Interface nützt nichts, wenn die gesamte Anwendung nicht über ein Deployment den Weg zum Anwender findet. Zeit, ein Deployment in die Wege zu leiten!

Der erste Artikel der Unity-Serie hat die Grundlagen geschaffen und gezeigt, was GameObjects und Prefabs sind und wie der Editor generell aufgebaut ist. Im zweiten Artikel haben wir uns mehr mit der Entwicklung des Heimcomputermuseums beschäftigt, haben eine Welt und eine Interaktion mit Türen und Museumsgegenständen implementiert. Und wir haben uns mit den ersten einfachen Animationen mit dem Animationssystem Mecanim beschäftigt. Abbildung 1 und das dazugehörige YouTube-Video [1] zeigen den Fortschritt aus dem zweiten Artikel.

rauber_unity3d_teil3_1.tif_fmt1.jpgAbb. 1: Fortschritt aus dem zweiten Artikel

In diesem Artikel wollen wir unser bestehendes Heimcomputermuseum etwas weiter ausbauen und das Museumsstück um ein User Interface erweitern. In diesem UI zeigen wir dem Benutzer weitere Informationen über das Museumsstück an. Die Daten dazu werden wir von einem API laden, das wir für diesen Artikel bereitstellen.

Die Wahl des User Interface in Unity

Zugegebenermaßen ist es gerade eine interessante Zeit, in die Unity-Entwicklung einzusteigen. Seit geraumer Zeit wird die Engine einer Generalüberholung unterzogen und viele Features werden erneuert oder ausgetauscht und alte Zöpfe abgeschnitten. Aus diesem Grund existieren aktuell drei Möglichkeiten, in Unity ein UI zu entwickeln.

Eine Möglichkeit wäre das Immediate Mode Graphical User Interface, kurz IMGUI. Es erlaubt das Erstellen von UIs gänzlich via Code, einen grafischen Designer gibt es nicht. Für ein UI für den Spieler sollte IMGUI nicht verwendet werden. Allerdings verwendet Unity IMGUI für den Editor selbst – also all das, was wir sehen, bspw. Hierarchy, Project oder Inspector. Würden wir eigene Erweiterungen für den Unity-Editor schreiben, müssten wir hierfür auch IMGUI verwenden. Da wir uns allerdings auf ein UI konzentrieren wollen, mit dem der Spieler interagiert, wird IMGUI in diesem Artikel nicht zum Einsatz kommen.

Die zweite Möglichkeit ist Unity (Graphical) User Interface, kurz Unity UI oder uGUI. Unity UI ist die aktuelle Variante, wie in Unity ein UI entwickelt werden kann, mit dem der Spieler interagiert. Im Unterschied zu IMGUI kann Unity UI nicht für den Editor selbst verwendet werden, sondern ausschließlich für Spieler-UIs. Unity UI bietet einen grafischen Designer, der etwas an die Arbeit mit WinForms oder WPF erinnert. In diesem Artikel werden wir uns mit dem Unity UI beschäftigen.

Zuletzt sei noch die dritte Möglichkeit genannt: UIElements, manchmal auch UI Toolkit. In der Zukunft soll UIElements sowohl IMGUI als auch uGUI ablösen. Der Ansatz von UIElements ist dem Web sehr nahe, so wird die Oberfläche mittels UXML beschrieben (ähnlich XAML), Styling erfolgt über USS (Unity-specific Style Sheets), einem Subset von CSS und UQuery, einer jQuery-ähnlichen Abfragesprache in C#, um Elemente anzusprechen – und das alles mittels eines grafischen Designers. Das bedeutet, dass wir in Zukunft in Unity bspw. mit der Flexbox arbeiten können und generell viel Wissen aus der UI-Entwicklung im Web in Unity einsetzen können. Aktuell kann UIElements nur für das UI im Unity-Editor genutzt werden, große Teile davon werden bereits als UIElements dargestellt. Bis wir UIElements auch für Spieler-UIs nutzen können, wird es noch einige Zeit dauern. Es existiert bereits ein Paket [2], mit dem gearbeitet werden kann, allerdings ist es betabedingt noch mit Vorsicht zu genießen.

Erste Schritte mit uGUI

Mit Hilfe von uGUI möchten wir unseren Museumsstücken ein UI anbieten, in dem weitere Informationen über ein Museumsstück gegeben werden. Die Informationen über das Museumsstück werden wir über ein API beziehen, das wir auf Heroku bereitstellen [3]. Das API ist mit .NET 5 entwickelt und der Code steht auf GitHub [4] zur Verfügung.

uGUI bietet als Toolkit einige vorgefertigte Elemente an, bspw. Texte, Buttons, Drop-down-Menüs, Scroll Views, Sliders etc. Was uGUI alles zu bieten hat, sehen wir, indem wir in Hierarchy einen Rechtsklick machen und im Menü auf den Punkt UI wechseln.

Generell werden alle UI-Elemente auf einem Canvas platziert. Das dient als Zeichenfläche und kann in drei verschiedenen Render Modes gezeichnet werden:

  • Screen Space – Overlay: In diesem Modus werden alle UI-Elemente oberhalb der Scene gezeichnet, sodass unser Canvas immer sichtbar ist und nicht durch ein GameObject überlagert werden kann. Dieser Modus ist der Standardmodus. Wenn sich die Bildschirmauflösung ändert, passt sich das Canvas automatisch an.

  • Screen Space – Camera: Dieser Modus ist ähnlich wie der Overlay-Modus, mit dem Unterschied, dass das Canvas eine Distanz/Entfernung zur Kamera hat. Alle GameObjects die hinter dem Canvas liegen, werden dahinter gezeichnet, alle GameObjects die vor dem Canvas liegen, überlagern das Canvas. Auch in diesem Fall passt sich das Canvas bei einer Änderung der Bildschirmauflösung an.

  • World Space: In diesem Modus verhält sich das Canvas wie ein normales GameObject; die Größe muss manuell gesetzt werden und die Elemente werden größer/kleiner, je nachdem, ob der Spieler sich dem World Space Canvas nähert oder entfernt. Dieser Modus ist praktisch für UIs, die Teil der Welt sind.

Für unser UI werden wir einen Canvas im Overlay-Modus benutzen. Dazu klicken wir rechts in Hierarchy, wählen UI und danach Canvas. Wir sehen, dass neben dem Canvas auch ein weiteres GameObject erzeugt wurde: das Event-System. Das Event-System ist dafür verantwortlich, Klicks auf unseren Canvas zu erkennen und so z. B. den echten Buttonklick auszulösen. Ohne das Event-System könnten wir nicht mit unserem UI interagieren.

Abbildung 2 zeigt, wie unser UI am Ende aussehen soll. Im oberen Teil haben wir eine Kopfleiste mit einem kleinen Thumbnail, einer Überschrift und einer Kurzbeschreibung. Darunter finden wir Buttons, um durch verschiedene Informationsseiten zu navigieren (eine klassische Tab-Bar mit Buttons). Unter der Buttonleiste ist ein einfaches Textfeld, in dem wir beliebigen (Rich) Text anzeigen können.

Für die klassische Tab-Bar mit Buttons benötigen wir zwei Prefabs: eins für den Button und eins für den Inhalt des Tabs. Das werden wir als Erstes erstellen.

rauber_unity3d_teil3_2.tif_fmt1.jpgAbb. 2: Beispiel, wie das UI aussehen soll

Erstellung eines Button-Prefabs

Über einen Rechtsklick in Hierarchy wählen wir UI | Button – TextMeshPro. Unity bringt zwei Arten von Textrendering im UI mit: zum einen die alte Variante (im Menü der Button ohne weiteren Zusatz) und zum anderen TextMeshPro, eine von Unity aufgekaufte Erweiterung. Es sollte immer die Variante mit TextMeshPro genutzt werden, da das alte Textrendering von Unity erhebliche Probleme beim Rendern von Text hat. TextMeshPro behebt diese Probleme und bringt zudem viele Features in Bezug auf Text mit, bspw. Farben, Farbverläufe, verschiedene Wrapping- und Overflow-Modi und eine Unterstützung von Rich Text in Form von HTML-ähnlichen Tags im Text [5].

Beim erstmaligen Hinzufügen eines Elements mit TextMeshPro öffnet sich automatisch der TMP Importer (Abb. 3). Dort muss einmalig der Button Import TMP Essentials angeklickt werden, damit Unity automatisch noch einige wichtige Ressourcen für TextMeshPro hinzufügt. Der zweite Button Import TMP Examples & Extras muss nicht gewählt werden. In Hierarchy sehen wir, dass der Button aus zwei GameObjects besteht, nämlich aus dem Button selbst und einem weiteren Kind für den Text. Die eigentliche Funktion des Buttons finden wir auf dem Button-GameObject. Was genau der Button anzeigt, bestimmen die Kinder. Im Standardfall ist das Text, es kann aber auch ein Bild oder Bild und Text sein, je nachdem, was wir benötigen. Wir wählen das Kind Text (TMP) an und stellen sicher, dass im Inspector der Punkt Auto Size abgewählt ist und die Font Size auf 14 eingestellt ist. Hier kann allerdings auch je nach Geschmack mit anderen Größen und Farben herumgespielt werden. Für den Artikel beschränken wir uns auf entwicklerhübsch. Auto Size ist praktisch, wenn ein Text innerhalb eines Minimums und Maximums automatisch skaliert werden soll, je nachdem, wie viel Platz zur Verfügung steht.

Als Nächstes erstellen wir das Prefab. Dazu ziehen wir per Drag and Drop den Button aus Hierarchy in Project. Danach löschen wir den Button wieder aus Hierarchy.

rauber_unity3d_teil3_3.tif_fmt1.jpgAbb. 3: TMP Importer

Erstellung eines Tab-Prefabs

Die gleiche Vorgehensweise nutzen wir, um ein Tab zu erstellen, in dem wir später weitere Informationen anzeigen. Dazu erstellen wir via Rechtsklick in Hierachy | UI | Text – TextMeshPro ein neues Textelement. Auch hier schalten wir Auto Size aus und stellen Font Size auf 16. Danach erzeugen wir ein Prefab, das wir mit „Tab“ benennen, und löschen es dann wieder aus Hierarchy heraus.

Aufbau des Information UI

In diesem Abschnitt wollen wir das UI erstellen, das wir in Abbildung 2 gesehen haben. Abbildung 4 zeigt den hierarchischen Aufbau, den wir Schritt für Schritt erstellen werden.

rauber_unity3d_teil3_4.tif_fmt1.jpgAbb. 4: Hierarchischer Aufbau des Information UI

Das zuvor erzeugte Canvas dient als Startpunkt. Deshalb benennen wir dessen...