
Dieser Artikel beschreibt die Optimierung von UI-Elementen von Projekten, die in Unity erstellt wurden. Basierend auf Informationen aus der offiziellen Dokumentation und persönlichen Erfahrungen habe ich versucht, die Funktionsprinzipien von UI-Elementen klar zu erklären. Auch hier finden Sie praktische Tipps, mit denen Sie die Leistung Ihres Projekts in Bezug auf die Benutzeroberfläche verbessern können.
Terminologie
UI-Elemente sind alle Elemente in Unity, die sich auf das Erstellen einer Benutzeroberfläche beziehen. Dies umfasst zum Beispiel: Schaltfläche, Text, Bild, Dropdown-Menü usw.
Canvas (Canvas) - das Grundelement der Benutzeroberfläche, das ein Container für den Rest der Elemente ist.
Mesh - eine Reihe von Parametern, die ein 3D-Modell beschreiben.
Ein Quad ist ein Netz, das ein Viereck ist.
Stapeln - Kombinieren von Objektnetzen zu einem großen Netz für ein schnelleres Rendern.
Draw-Call - Ein Befehl zum Zeichnen von der Engine zur Grafik-API (z. B. OpenGL oder Direct3D).
Transparente Warteschlange - Eine Warteschlange zum Rendern transparenter Objekte.
Alpha-Blending (Alpha-Blending) - Ein Algorithmus zum Mischen von Pixeln auf dem Alpha-Kanal, um ein Bild mit Transparenz zu erhalten.
Atlas ist eine Art Ressource, die mehrere Texturen zu einer kombiniert.
Einführung
Bei der UI-Optimierung gibt es keine universellen Regeln, die in jeder Situation funktionieren. Es kommt darauf an, ein Gleichgewicht zwischen den Chargenkosten und der Anzahl der Draw Calls zu finden. Es können vier Hauptprobleme unterschieden werden:
- GPU-Last zu hoch (Überlast auf dem Render);
- zu viel CPU-Last beim Neuerstellen der Zeichenfläche;
- zu viele sich ändernde Elemente, die zum Wiederaufbau der Leinwand führen;
- Die CPU-Auslastung ist für die Netzgenerierung zu groß (normalerweise mit Text verbunden).
Rendering der Unity-Benutzeroberfläche
Das Grundelement der Unity-Benutzeroberfläche ist die Zeichenfläche. Er ist für das Generieren, Sortieren und Rendern von Netzen untergeordneter Schnittstellenelemente verantwortlich. Alle UI-Elemente müssen untergeordnete Elemente einer beliebigen Leinwand sein, da sie sonst nicht im Spiel angezeigt werden.

Das Rendern erfolgt vom entferntesten zum am weitesten von der Kamera entfernten Objekt (von hinten nach vorne) in der transparenten Warteschlange mit Alpha-Überblendung.
Unabhängig davon sollte beachtet werden, dass die Transparenz der UI-Elemente die Leistung NICHT beeinträchtigt. Selbst wenn das Element vollständig aus „undurchsichtigen“ Pixeln besteht, wird es dennoch mithilfe der Alpha-Überblendung gerendert.
Es ist auch wichtig zu verstehen, dass beim Rendern alle Pixel aller aktiven Elemente verarbeitet werden. Es kommt nicht darauf an, ob sie sichtbar, von anderen Objekten blockiert oder sogar vollständig transparent sind.
Neugestaltung der Benutzeroberfläche
Das Neugestalten der Benutzeroberfläche ist ein mehrstufiger Prozess, bei dem die Netze jedes UI-Elements erstellt und versucht werden, diese Netze zu patchen, um die Anzahl der Draw-Aufrufe zu minimieren.
Der Wiederaufbau erfolgt in vier Schritten:
- Strukturen von Elementen werden analysiert.
- Netze aller aktiven Elemente, einschließlich Elemente ohne Transparenz, werden neu erstellt.
- Erstellt Materialien zum Vernetzen von Elementnetzen neu.
- Alle Elemente werden entsprechend ihrer Reihenfolge gezeichnet.
Die neu erstellte Zeichenfläche wird zwischengespeichert und wiederverwendet, bis eines der Elemente in der Zeichenfläche als geändert markiert wird.
Schmutzige Objekte werden markiert, die aktiviert oder deaktiviert wurden. die Material, Position, Maßstab, Rotation geändert haben; Der Textwert der Textkomponente hat sich geändert. Neuzuweisung des Elternteils usw.
In diesem Fall enthält die erneute Erstellung der Zeichenfläche mindestens ein geändertes Element. Dies gilt zwar nur für die Zeichenfläche, in der sich das Element befindet. Das heißt, Änderungen an Elementen in untergeordneten Leinwänden wirken sich nicht auf übergeordnete aus.
Je mehr Elemente sich auf der Leinwand befinden, desto höher sind die Kosten für das Analysieren und Sortieren von Objekten.
Vernetzung
Durch das Zusammenführen von Meshes oder Batching wird die Belastung der GPU verringert, indem die Anzahl der Draw-Aufrufe verringert wird. Während des Dosiervorgangs werden die Maschen nach Tiefe sortiert und auf Überlappung überprüft. Beim Übergang vom entfernten zum nahen Element (oder vom oberen zum unteren Element in der Hierarchie) werden Objekte mit denselben Materialien oder Texturen zu einem Netz innerhalb derselben Leinwand kombiniert. Zu diesem Zweck sollten sich keine Objekte mit anderen Materialien dazwischen befinden. Außerdem sollten Objekte mit anderen Materialien die gebackenen Objekte nicht mit ihren Gesamtbehältern überlappen. Der Stapelvorgang erfolgt über mehrere Threads. Die Leistung hängt stark von der Anzahl der Kerne im Prozessor ab.
Text kann mit anderem Text flattern, wenn er dieselbe Schriftart hat. Es spielt keine Rolle, ob die Schriftarteinstellungen und -stile gleich oder unterschiedlich sind. Wenn die Schriftarten unterschiedlich sind, wird der Text nicht gerollt.
Es sollte auch berücksichtigt werden, dass Text ein Objekt mit seinem Gesamtcontainer überlappen kann und eine solche Überlappung leicht übersprungen werden kann.

Betrachten Sie ein Beispiel. Es gibt drei Objekte A, B und C, die auf diese Weise in einer Hierarchie angeordnet sind:


Im Bild links werden die Objekte A und C zusammengeführt, weil haben das gleiche Material und schneiden sich nicht mit Objekt B. Im Bild rechts werden die Objekte A und C nicht kombiniert, weil Es gibt einen Schnittpunkt mit Objekt B.
Allgemeine Tipps zur Optimierung der Benutzeroberfläche
Bevor Sie mit der Optimierung beginnen, wird dringend empfohlen, die Benutzeroberfläche zu profilieren. Dies hilft bei der Identifizierung von Engpässen, die zu Leistungseinbußen führen (falls vorhanden). Für die Profilerstellung gibt es viele Tools, die sowohl in Unity (Unity Profiler) als auch in Tools von Drittanbietern integriert sind. In diesem Artikel werden die Probleme der UI-Profilerstellung jedoch nicht behandelt.
Hier einige Vorschläge zur Optimierung Ihrer Benutzeroberfläche in Unity:
- Schalten Sie unsichtbare Objekte aus. Wenn ein Element von einem undurchsichtigen Element überlappt wird, müssen Sie sein GameObject oder das übergeordnete GameObject des überlappenden Elements deaktivieren. Gleichzeitig werden weiterhin Schnittstellenelemente mit Alpha auf 0 gezeichnet. Für solche Objekte müssen Sie Cull Transparent Mesh in der Canvas Renderer-Komponente aktivieren oder einfach unsichtbare Objekte deaktivieren.

- Deaktivieren Sie Weltobjekte, die von einer undurchsichtigen Oberfläche ausgeblendet werden. Wenn die Benutzeroberfläche nicht die ganze Welt abdeckt, können Sie sie in der Render-Textur speichern und die Weltkamera ausschalten.
- Minimieren Sie die Anzahl der zu zeichnenden Pixel. Kombinieren Sie so viele Bilder wie möglich zu einem. Zum Beispiel ist es sinnvoll, die Schaltflächen zu einem einzelnen Sprite zu machen, anstatt Ebenen mit Hintergrund, Strich, Schaltflächenkörper usw. zu trennen. Dies verringert die Flexibilität bei der Arbeit mit solchen Elementen und kann zu einer Verstopfung der Ressourcen führen. Daher muss ein Kompromiss angestrebt werden.

- Vermeiden Sie leere Elemente, die nur zur Organisation der Struktur dienen (verwenden Sie keine Elemente als Namen von „Ordnern“ in der Dokumenthierarchie).
- Vermeiden Sie es, Gegenstände zu kreuzen, die nicht miteinander backen können. Wenn möglich, ändern Sie am besten die Position in der Hierarchie, die Größe des Containers oder die Position überlappender und nicht zusammenbackender Elemente.
- Verwenden Sie für dynamische Elemente eine separate oder verschachtelte Zeichenfläche. So minimieren Sie die Kosten für das Sortieren und Wiederherstellen der Struktur der Zeichenfläche, die eine große Anzahl von Elementen enthält. Verschachtelte Leinwände sind bequemer, weil erben die Einstellungen der übergeordneten Zeichenfläche. Gleichzeitig werden beim Ändern der übergeordneten Zeichenfläche auch alle verschachtelten Bereiche neu erstellt. Dies ist ziemlich selten, aber es passiert (zum Beispiel beim Ändern der Bildschirmauflösung). Beachten Sie, dass Objekte aus verschiedenen Leinwänden oder verschachtelten Leinwänden NICHT für das gemeinsame Rendern gebacken werden. Es wird empfohlen, die Leinwände nach der Regelmäßigkeit der Aktualisierung der Elemente zu unterteilen. Statische Elemente müssen auf einer separaten Leinwand platziert werden, dann werden sie nur einmal gezeichnet. Wenn es Elemente gibt, die sich ständig ändern, ist es besser, sie auf einer anderen Leinwand zu kombinieren, weil Sie werden sich immer noch gegenseitig wieder aufbauen. Das Ändern von Objekten kann durch die Aktualisierungsrate auch in mehrere Leinwände unterteilt werden. Beispielsweise werden Elemente, die in jedem Frame aktualisiert wurden, in eine Zeichenfläche eingefügt, und Elemente, die in einem anderen weniger häufig aktualisiert werden.
- Durch Deaktivieren von Pixel Perfect wird die Produktivität erheblich gesteigert. Dies gilt insbesondere für ständig aktualisierte Objekte mit einer großen Anzahl von Elementen (z. B. Bildlaufinventar).

Die Leinwand

Verschachtelte Leinwand - Wenn Sie die Zeichenfläche deaktivieren müssen, deaktivieren Sie das Objekt, das sie enthält, nicht (über die Funktion SetActive ). Beim nächsten Einschalten werden die Elemente dieser Zeichenfläche als geändert markiert und alle Elemente werden neu erstellt. Es ist besser, die Canvas-Komponente selbst auszuschalten, da sich dann die gesamte Struktur und die gebackenen Daten nicht ändern. Wenn Sie die Canvas-Komponente das nächste Mal einschalten, beginnen sie einfach mit dem Zeichnen.

- Installieren Sie für Leinwände mit Bildschirmbereich - Kamera oder Weltraum, die im Parameter Rendermodus ausgewählt wurden, immer eine Kamera. Wenn Sie es nicht installieren, durchsucht das Benutzeroberflächensystem in jedem Frame Object.FindObjectWithTag , um Camera.main zu finden. Dies wirkt sich auf die Leistung aus.
- Um nicht mehrere identische Texturen zu erstellen, können Sie eine in Graustufen erstellen und durch die Bildkomponente „malen“, indem Sie die gewünschte Farbe auswählen.

- Lassen Sie das Raycast-Ziel- Flag nur für Elemente, die Eingabeereignisse benötigen, und entfernen Sie den Rest. Standardmäßig ist das Raycast-Ziel für viele Elemente (Bild, Text usw.) aktiviert. Dies verkompliziert und verlangsamt die Arbeit der Raycaster- Komponente, die Eingabeereignisse in der Unity-Benutzeroberfläche verarbeitet. Beim Klicken oder Tippen wird die gesamte Hierarchie der Elemente durchlaufen und nach allen Grafikkomponenten mit gesetztem Raycast-Ziel- Flag gesucht. Anschließend werden sie auf die Möglichkeit von Eingabeereignissen überprüft und nach erfolgreichem Bestehen der Prüfungen zur Trefferliste hinzugefügt. Danach wird die Trefferliste nach Tiefe sortiert, Objekte außerhalb des Bildschirms werden verworfen. Als Ergebnis gibt es die endgültige Trefferliste.
In der Unity-Benutzeroberfläche haben viele Komponenten (Bild, Text usw.) das Raycast- Zielflag.

Raycast-Ziel auf der Bildkomponente.

TextMeshPro hat es auf der Registerkarte Zusätzliche Einstellungen ausgeblendet.

Für TextMeshPro können Sie die Standardeinstellung für das Raycast-Ziel unter Player-Einstellungen -> TextMest Pro -> Einstellungen -> Raycast-Ziel aktivieren festlegen .
Elemente werden getestet, wenn:
- Raycast-Ziel aktiviert
- das Element selbst wird eingeschaltet und aktiviert;
- Die Einfügemarke befindet sich am Schnittpunkt mit RectTransform.
Es ist auch sinnvoll, das Raycast-Zielflag von untergeordneten Elementen zu entfernen, wenn das Stammobjekt es bereits hat und die untergeordneten Elemente mit seiner Geometrie vollständig überlappt. Zum Beispiel die Standardschaltfläche der Unity-Benutzeroberfläche.

Das Bild überlappt den Text vollständig mit seiner Form. In diesem Fall können Sie das Raycast-Ziel aus der Textkomponente entfernen.

Wenn nicht alle Canvas-Elemente auf Eingabeereignisse warten, können Sie die Graphic Raycaster- Komponente aus dem Canvas / verschachtelten Canvas entfernen.
Arbeiten Sie mit Text und dessen Optimierung
Der Text in der Unity-Oberfläche besteht aus Gittern, in denen jedes Symbol ein eigenes Quad erstellt. Das Netz wird jedes Mal neu erstellt, wenn sich der Wert des Texts ändert. Die Neuerstellung erfolgt auch, wenn die Textkomponente oder deren übergeordnetes Element aus- und wieder eingeschaltet wurde.
Standardmäßig werden Schriftarten in Unity als dynamisch hinzugefügt. Für jede dynamische Schriftart, die in der Textkomponente auf der Bühne verwendet wird, wird ein Atlas erstellt. In diesem Atlas sind nur verwendete Zeichen enthalten. Wenn das Textfeld beispielsweise den Text "Neuer Text" enthält, enthält der dafür erstellte Atlas die Zeichen "N", "e", "w", "T", "x" und "t". Für jedes Zeichen, das sich in Größe oder Stil unterscheidet, wird im Atlas eine Darstellung erstellt.

Text auf der Bühne

Schriftatlas
Wenn sich während der Ausführung des Programms der Inhalt der Textkomponente ändert und Zeichen angezeigt werden, die nicht im Atlas enthalten sind, wird der gesamte Atlas neu erstellt. Wenn in der Textur des Atlas freier Speicherplatz vorhanden ist, werden die erforderlichen Symbole einfach dort hinzugefügt. Gleichzeitig werden Zeichen, die derzeit nicht verwendet werden, nicht gelöscht. Wenn im Atlas nicht genügend Platz für neue Zeichen vorhanden ist, wird seine Größe verdoppelt und basierend auf den in den aktiven Textkomponenten verwendeten Zeichen erneut gefüllt.
Wenn für ein Projekt eine genau definierte Anzahl von Zeichen festgelegt ist, z. B. nur das lateinische Alphabet, lohnt es sich, statische Schriftarten zu verwenden, die permanent im Speicher gespeichert sind. Wenn Ihr Projekt eine große Anzahl von Zeichen zulässt, ist es besser, sich mit dynamischen Schriftarten zu befassen.
Sie können die Leistung auch verbessern, indem Sie die Textkomponente durch ein Sprite ersetzen. Zum Beispiel können die im Spiel erscheinenden Zahlen (Punktzahl) mithilfe von Sprites aus einem Atlas erstellt werden, der nur einen Satz der erforderlichen Zeichen enthält. In diesem Fall fallen keine Kosten für die Neuerstellung der Leinwand und des Atlas der Schrift an.
Die Verwendung von Fallback-Schriftarten, die in den Schriftarteneinstellungen im Feld "Schriftnamen" aufgeführt sind, erhöht den verwendeten Speicher. Dies macht sich insbesondere bei piktografischen Schriftarten bemerkbar.
Es wird nicht empfohlen, Best Fit zu verwenden , da Diese Option führt zu einem schnellen Überlaufen des Atlas und bewirkt dessen Umstrukturierung.
Die beste Anpassung ignoriert die Einstellungen für die Schriftgröße und versucht, den Text in das Umrissrechteck der Textkomponente einzupassen.
Nun ein paar Worte zu TextMeshPro (TMP) , einem beliebten Ersatz für die Standard-Unity-Textkomponente. TextMeshPro erstellt außerdem jedes Mal ein neues Raster, wenn sich der Wert des Texts ändert. TMP-Text verwendet jedoch keine dynamischen Schriftarten. Dafür werden im Voraus Schriftatlanten generiert, die alle notwendigen Zeichen enthalten. Wenn für einen Text in der Szene kein Zeichen in der Schriftart vorhanden ist, die der Komponente zugewiesen ist, beginnt TMP mit der Suche in Sicherungsschriftarten. Wenn dort nichts vorhanden ist, versucht TMP, dieses Zeichen in allen heruntergeladenen Schriftarten zu finden.
Die beste Anpassung in TMP verursacht keine Probleme wie eine normale Textkomponente und kann daher verwendet werden.
Eine große Anzahl von Schriftarten mit unterschiedlichen Lokalisierungen oder großen Atlanten von Schriftarten kann viel Speicherplatz beanspruchen. Daher ist es besser, nur die für eine bestimmte Lokalisierung erforderlichen Schriftarten vorzuladen.
World Space empfiehlt die Verwendung von TextMeshPro anstelle von TextMeshProUGUI .
TextMeshProUGUI wird in Leinwänden verwendet.
Sprite-Atlanten
Sprite-Atlanten sind eine Art Ressource, die mehrere Texturen zu einer kombiniert. Mit ihnen können Sie die Anzahl der Draws ( Draw Calls ) reduzieren und die Produktivität steigern.
Atlas Erstellung.
Erstellen Sie einen Atlas: Asset> Erstellen> Sprite-Atlas .
Wählen Sie den Atlas aus und fügen Sie das erforderliche Sprite in Objekte zum Verpacken ein .

Klicken Sie auf Packvorschau, um eine Vorschau des Atlas anzuzeigen.

Beachten Sie, dass der Atlas auch dann vollständig geladen wird, wenn ein oder mehrere Sprites aus dem Atlas in der Szene verwendet werden. Daher ist es nicht sinnvoll zu versuchen, alle Bilder in einen riesigen Atlas einzubetten, der auf Geräten mit kleinem RAM seinen greifbaren Teil übernehmen kann. Es ist besser, in einige kleinere Atlanten zu unterbrechen, beispielsweise den Atlas der Benutzeroberfläche des Spielmenüs und den Atlas der Benutzeroberfläche des Spielmodus.
Vermeiden Sie große Leerstellen im Atlas, um nicht zu viel Speicherplatz zu belegen. Dazu können Sie die Größe des Atlas ändern oder zusätzliche Bilder hinzufügen, um den leeren Raum so weit wie möglich zu füllen.


Für Bilder, die nicht im Atlas enthalten sind, müssen Sie die richtigen Einstellungen auswählen.
Für jedes Komprimierungsformat gibt es Anforderungen, unter denen es effizient arbeitet. Die häufigsten Bildanforderungen:
- Breite und Höhe müssen ein Vielfaches der Zweierpotenz sein;
- Breite und Höhe müssen ein Vielfaches von 4 sein;
- beide vorhergehenden Absätze zusammen.
Andernfalls wird die Textur nicht komprimiert und es entstehen zusätzliche Gerätespeicherkosten.
Bei der Auswahl eines Komprimierungsformats teilt Unity Ihnen mit, ob Anforderungen für das ausgewählte Format nicht erfüllt sind.

Vergessen Sie auch nicht, dass sich die Formate vom Zielgerät unterscheiden. Weitere Informationen und Empfehlungen zu Formaten finden Sie in der offiziellen Dokumentation :
Fassen Sie die Optimierungsmethoden zusammen
- Deaktivieren Sie unsichtbare und transparente Objekte
- Minimieren Sie die Anzahl der Elemente
- Vermeiden Sie es, Gegenstände zu kreuzen, die nicht miteinander backen können
- Verteilen Sie Elemente nach Leinwand basierend auf der Aktualisierungsrate
- Deaktivieren Sie für Leinwände mit häufig aktualisierten Elementen Pixel Perfect
- Deaktivieren Sie das Raycast-Ziel für nicht anklickbare Elemente
- Entfernen Sie die Graphic Raycaster-Komponente auf der Leinwand, für die nicht alle Elemente anklickbar sind
- Verwenden Sie für normale Textkomponenten nicht Best Fit
- Verwenden Sie für TextMeshPro im Weltraum TextMeshPro anstelle von TextMeshProUGUI. TextMeshProUGUI wird in Leinwänden verwendet
- Stellen Sie die Kamera bei Bedarf in den Canvas-Einstellungen ein
- Deaktivieren Sie die Zeichenfläche, indem Sie die Zeichenflächenkomponente deaktivieren
- Verwenden Sie Graustufen-Sprites und färben Sie die Einstellungen der Bildkomponenten ein
- Verwenden Sie Sprite-Atlanten
- Verwenden Sie die richtige Größe und das richtige Komprimierungsformat für Texturen, die nicht im Atlas enthalten sind
Quellen:
Umfassende Informationen zur Optimierung der Unity-Benutzeroberfläche
Eine andere offizielle Quelle zu diesem Thema enthält Informationen in einer präziseren Form.
Atlas White Papers
Zusätzliche Informationen zu Texturkomprimierungsformaten