You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Basics

Unter Layering verstehe ich die Aufteilung von Objekten in Ebenen ("Layers"), insbesondere um Vordergrund und Hintergrund zu unterscheiden. Gerade für Dinge wie Alerts oder andere Arten von Pop-ups ist es für die UI wichtig, eine solche Sortierung über Layering sicherzustellen.


Abbildung 1: Der rote Alert sollte immer über allen anderen Elementen erscheinen.

Wie können wir also sicherstellen, dass unser Alert immer vorne ist, so wie es in Abbildung 1 zu sehen ist? Im Kapitel über das Canvas ging es bereits darum, wie man GameObjects innerhalb eines Canvas sortiert und dann wiederum Canvasses untereinander mittels Canvas-Render-Modes oder Sortieroptionen sortiert. Gegebenenfalls muss die UI sich auch noch gegen Objekte der Welt sortieren - das ist vor allem für Partikeleffekte interessant - weswegen es sinnvoll ist die Hierarchie und das Verhalten von Sortierfunktionen der Renderer zu kennen.


Abbildung 2: Die Komponente Sprite Renderer. Unten sieht man die Sortieroptionen.

Für Layering von transparenten Objekten (z.B. Canvas, Sprites) gilt folgende Hierarchie:

  1. Sorting Layer
  2. Sorting Wert
  3. Distanz zur Kamera (Transparenzachse; standardmäßig entlang Z)

Bedeutet also:

  1. Sind zwei Objekte auf dem gleichen Sorting-Layer?
    1. Ja - Sorting-Wert wird betrachtet.
    2. Nein - Das höhere Layer wird vorne angezeigt.
  2. Haben die Objekte den gleichen Sorting-Wert?
    1. Ja - Die Z-Position wird betrachtet.
    2. Nein - Der höhere Sorting-Wert ist vorne.
  3. Der geringere Z-Wert ist vorne.

Anmerkungen: 

  • Diese Hierarchie ist vereinfacht
    Es gibt noch diverse andere Möglichkeiten Renderer zu sortieren. Die genaue Aufschlüsselung findet sich hier.
  • Es gibt standardmäßig 2 Render Queues "Opaque" und "Transparent", welche auch in dieser Reihenfolge sortiert werden.
    Zur Erinnerung: Canvas und Sprites sind in der transparent Queue,
  • Die Transparenzachse kann man beliebig einstellen
    z.B. auf Y an Stelle von Z. Das ist beispielsweise hilfreich für 2D Top-Down-Spiele.


Um die Sortierung von Weltobjekten zu erleichtern gibt es die Sorting Group, um welche es als nächstes geht.

Sorting Group


Abbildung 3: Die Komponente Sorting Group

Mit der Sorting Group gruppiert man ein GameObject und seine Childs als Einheit für das Rendern, ähnlich wie es das Canvas tut. Ein Beispiel dafür wäre ein Charakter, der aus mehreren, einzelnen Sprites besteht. Außerhalb der Gruppe gelten jetzt die Sortieroptionen bzw. die Z-Position des Gruppen-Parents für alle Childs. Innerhalb werden Renderer wiederum nach den für sie geltenden Regeln sortiert: Beispielsweise gelten für Sprites Sorting-Layer und Wert, während Z zugunsten der Hierarchie ignoriert wird (erneut, wie beim Canvas). Bei 3D-Renderern wird nach Z sortiert und bei gleichem Z-Wert der Hierarchie nach.


Abbildung 4: Sorting Group sortiert gegen Sprite

In Abbildung 4 sieht man beispielhaft die Anwendung einer Gruppe, um die drei kleinen Kreise zu gruppieren und diese gemeinsam gegen den grünen Kreis zu sortieren. Die Gruppe befindet sich vorne, da sie den höheren Sortierwert ( 1 gegen 0) hat. Innerhalb der Gruppe haben alle Kreise den gleichen Sortierwert, entsprechend werden die Kreise der Hierarchie nach sortiert. Diese Sortierung ist abweichend von den Z-Werten, da diese ignoriert werden.

Abbildung 5: Ein grauer Würfel wird einsortiert


Insbesondere bei 3D-Renderern ist wichtig, dass Sortieroptionen nur auf transparente Geometry angewendet werden. Wird der Render-Mode "Opaque" verwendet sortieren 3D-Renderer mit Sorting-Groups trotzdem über die Z-Position gegen andere Sorting-Groups. Wenn der richtige Render-Mode verwendet wird, kann man nun mit der Sprting-Group-Komponente einen Sortierwert zuweisen. Auf diese Weise landet der graue Würfel in Abbildung 5 zwischen den Elementen aus der vorherigen Abbilung 4.


Abschließend sind Sorting groups also für zwei Anwendungen  besonders wichtig:

  1. Gruppieren von Objekten, die optisch eine Einheit sein sollen - z.B. Charakter aus mehreren Sprites,
  2. Anwendung von Sortieroptionen auf (transparente) 3D-Renderer.


Partikel in der UI


Partikeleffekte für die UI sind von Unity nicht von Haus aus unterstützt. Man kann zwar ein herkömmliches Partikelsystem an Childs eines Canvas hängen, aber das Sortieren funktioniert leider nicht korrekt:

Abbildung 5a: Partikelsystem als Child des grünen Play-Buttons

Abbildung 5b: Hierarchie zu 5a

In Abbildung 5a sehen wir, dass die Partikel nicht nur hinter den UI Elementen des Parent-Canvas "Foreground" verschwinden, sie liegen auch hinter dem darunterliegenden Canvas "Background".

Besser ist es Partikelsysteme in der Welt zu belassen. Dann kann man sie auch einfacher gegen die UI sortieren, in dem man den richtigen Canvas Render Mode wählt (siehe Canvas).


Abbildung 6a: Szenen-Ansicht des Screen Space Camera Setups

Abbildung 6b: Ansicht im Spiel

Für die Abbildung 6a habe ich die beiden Canvasses auf "Screen Space - Camera" umgestellt und das Partikelsystem dazwischen geschoben. Im Gameview (Abbildung 6b) tauchen die Partikel nun ordnungsgemäß zwischen Vorder- und Hintergrund-Canvas auf. Bei diesem Setup entsteht natürlich die Schwierigkeit, dass man das Partikelsystem korrekt platzieren muss. Das Ganze für statische Elemente per Hand aufzusetzen erscheint noch machbar, aber sobald Dinge dynamisch werden (Bildschirmgrößen bei Mobile, Partikelsysteme dynamisch instanziieren) braucht es ein selbstgeschriebenes System.

Um sich das Layouting zu erleichtern, kann man die Partikel trotzdem im Canvas belassen und auf ein Rendertextur-Setup zurückgreifen.

[Beispiel]

Hier werden die Partikel von einer separaten Kamera gerendert, deren Bild dann auf der Rendertextur angezeigt wird.

Zuletzt noch ein sehr gutes Package, was neben dem Rendertextur Ansatz auch noch andere Lösungen bietet: hier.


Anmerkung: Ein weiterer Grund warum Partikel besser nicht in der UI sein sollten ist Performance. Partikelsysteme sind konstant in Bewegung und würden das Canvas immer wieder neu zeichnen lassen (mehr dazu im Kapitel Performance).

Beispiel


Wie man seine UI am besten layered ist sehr stark vom Spiel abhängig. Um eine Idee davon zu haben kann man sich beispielsweise folgende Fragen stellen:

  • Ist die UI immer vorne?

Die UI könnte ein klassisches HUD sein - in diesem Fall nutzt man ganz einfach den Modus "Screen Space - Overlay" und sortiert verschiedene Canvasse über den Sorting Wert.

  • Benutze ich Z als Achse für Sortierung von Transparenz?

In diesem Fall würde ich keinen "Screen Space - Camera" Modus verwenden. Diese Art von Canvas sortiert sich immer nach Abstand zur Kamera auf Z - ihr X- und Y-Wert ist immer 0. Entsprechend könnten Weltobjekte nun ungewollt vor der UI erscheinen und es wird unmöglich die Sortierung im Scene View nachzuvollziehen.

  • Soll UI dynamisch Spielobjekten folgen?

Canvas mit "World Space" ist dein Freund. Sortiert werden kann das Canvas dann über Abstand zur Kamera oder mittels Sortieroptionen.

  • Was ist wenn UI hinter Spielobjekten auftauchen soll?

Angenommen wir haben ein 2D-Spiel mit Seitenansicht. Es wäre denkbar, dass z.B. Texte zwischen Spielebene und Hintergrund auftauchen sollen.

[Beispiel]

Für diesen Effekt sollten wir "Screen Space - Camera" oder "World Space" verwenden. Mit beiden Optionen können wir entsprechend unserer Szene die UI entweder über Tiefe oder Sortieroptionen einsortieren. Wenn sich diese UI dem Bildschirm oder der Kamera anpassen soll ist "Screen Space - Camera" zu verwenden.

Ein solches Setup erlaubt es auch Partikelsysteme in der Welt vor bzw. hinter der UI zu rendern. Warum das sehr praktisch ist steht im Kapitel über Partikel.

Wenn UI gegen Welt sortiert wird stellt sich dann die Frage nach der Sortierung:

  • Benutze ich Sortieroptionen oder Distanz zur Kamera bzw. Transparenzachse Z?

Meiner Meinung nach schließen sich diese beiden Optionen ein wenig aus und bieten unterschiedliche Vor- bzw. Nachteile. Das liegt vor allem an der zuvor beschriebenen einfachen Hierarchie - Sortieroptionen werden immer vor Z angewendet. Letztendlich muss die Wahl hier vor allem anderen mit der Sortierung der Spielszenen funktionieren.

Ich halte folgende Kombinationen für sinnvoll:

  • Alles sortiert sich nach Tiefe,
  • Alles sortiert sich mit den Sortieroptionen,
  • Global werden Sortieroptionen verwendet, aber UI sortiert sich intern nach Z.

Eine Sortierung nach Tiefe bietet vor allem den "What you see is what you get" - Vorteil. Wenn wir im Scene View auf 3D schalten, können wir unser Layering ganz bequem überblicken.

[Beispiel]

Die verschiedenen Ebenen der Spielszene könnten mit einer Sorting Group versehen werden, damit man diese intern über Sortieroptionen sortieren kann.

[Beispiel]

Nachteil ist natürlich, dass sie nicht funktioniert, wenn Z nicht die Transparenzachse ist - also für Top-Down eher nicht zu gebrauchen.

Wenn die Transparenzachse oder die Szenenhierarchie eine Sortierung per Tiefe nicht zulässt, eignen sich die Sortieroptionen am besten, auch wenn sie die Sortierung unübersichtlicher machen.

Ein Mittelweg kann es sein allein die Sortierung der UI über Z zu regeln und für die Welt Sortieroptionen zu nutzen. Dafür würde man alle Canvasses auf ein Vordergrundlayer verschieben, das über dem Weltlayer liegt. So behält man sich den Überblick der Tiefensortierung bei. 

[Beispiel]

  • No labels