Hero background image
Verwaltung der GPU-Nutzung für PC- und Konsolenspiele

Dies ist der dritte Teil einer Reihe von Artikeln, die Optimierungs-Tipps für Ihre Unity-Projekte enthalten. Verwenden Sie sie als Leitfaden für die Ausführung mit höheren Bildraten und weniger Ressourcen. Wenn Sie diese bewährten Verfahren ausprobiert haben, sollten Sie sich die anderen Seiten dieser Reihe ansehen:

Verstehen Sie die Grenzen Ihrer Zielhardware und wissen Sie, wie Sie die GPU profilieren können, um das Rendering Ihrer Grafiken zu optimieren. Probieren Sie diese Tipps und bewährten Verfahren aus, um die Arbeitsbelastung der GPU zu verringern.

Viele weitere Best Practices finden Sie in dem kostenlosen E-Book, Optimieren Sie die Leistung Ihrer Spiele für Konsole und PC.

SRP Batcher in der Unity-Engine
SRP BATCHER HILFT IHNEN DABEI, ZEICHNUNGSAUFRUFE ZU BÜNDELN.
Batching von Ziehungsaufrufen verwenden

Um ein Spielobjekt auf dem Bildschirm zu zeichnen, ruft Unity die Grafik-API (z. B. OpenGL, Vulkan oder Direct3D) auf. Jeder Ziehungsaufruf ist ressourcenintensiv.

Zustandsänderungen zwischen Zeichnungsaufrufen, wie z. B. das Umschalten von Materialien, können auf der CPU-Seite einen Leistungs-Overhead verursachen. PC- und Konsolen-Hardware kann viele Zeichenaufrufe tätigen, aber der Overhead jedes Aufrufs ist immer noch hoch genug, um den Versuch zu rechtfertigen, ihn zu reduzieren. Auf mobilen Geräten ist die Optimierung von Zugriffen unerlässlich. Sie können dies mit der Stapelverarbeitung von Zeichnungsaufrufen erreichen.

Das Stapeln von Zeichnungsaufrufen minimiert diese Zustandsänderungen und reduziert die CPU-Kosten für das Rendern von Objekten. Unity kann mit der High Definition Render Pipeline (HDRP) oder der Universal Render Pipeline (URP) mehrere Objekte zu weniger Stapeln zusammenfassen und dabei verschiedene Techniken anwenden:

  • SRP-Dosierung: Aktivieren Sie den SRP Batcher in der Pipeline-Anlage unter Erweitert. Bei Verwendung kompatibler Shader reduziert der SRP Batcher die GPU-Einstellungen zwischen den Zeichenaufrufen und sorgt dafür, dass die Materialdaten im GPU-Speicher erhalten bleiben. Dies kann auch Ihre CPU-Rendering-Zeiten erheblich beschleunigen. Verwenden Sie weniger Shader-Varianten mit minimalen Schlüsselwörtern, um das SRP-Batching zu verbessern. Lesen Sie in der SRP-Dokumentation nach, wie Ihr Projekt von diesem Rendering-Workflow profitieren kann.
  • GPU-Instanzierung: Wenn Sie eine große Anzahl von identischen Objekten mit demselben Mesh und Material haben, verwenden Sie GPU-Instanzierung, um sie über die Grafikhardware zu stapeln. Um die GPU-Instanzierung zu aktivieren, wählen Sie Ihr Material im Projektfenster des Inspektors aus und aktivieren Sie die Option Instanzierung aktivieren.
  • Statische Dosierung: Bei nicht bewegter Geometrie kann Unity Zeichnungsaufrufe für Meshes, die dasselbe Material verwenden, reduzieren. Dies ist effizienter als die dynamische Stapelverarbeitung, verbraucht aber mehr Speicher. Markieren Sie alle Meshes, die sich nie bewegen, im Inspektor als statische Meshes. Unity kombiniert alle statischen Meshes zur Erstellungszeit zu einem großen Mesh. Mit der Klasse StaticBatchingUtility können Sie diese statischen Chargen auch zur Laufzeit erstellen (z. B. nach der Generierung einer prozeduralen Ebene von nicht beweglichen Teilen).
  • Dynamische Dosierung: Bei kleinen Meshes kann Unity Scheitelpunkte auf der CPU gruppieren und transformieren und sie dann in einem Durchgang zeichnen. Beachten Sie jedoch, dass Sie dies nur verwenden sollten, wenn Sie genügend Low-Poly-Meshes haben (nicht mehr als 300 Scheitelpunkte pro Mesh und 900 Scheitelpunktattribute insgesamt). Andernfalls wird bei der Suche nach kleinen Meshes für die Stapelverarbeitung CPU-Zeit verschwendet.

Sie können die Dosierung auf einige einfache Arten optimieren:

  • Verwenden Sie so wenig Texturen wie möglich in einer Szene. Für weniger Texturen werden weniger einzigartige Materialien benötigt, so dass sie leichter zu chargenweise verarbeitet werden können. Verwenden Sie außerdem, wo immer möglich, Texturatlanten.
  • Erstellen Sie Lichtkarten immer mit der größtmöglichen Atlasgröße. Weniger Lightmaps erfordern weniger Änderungen des Materialzustands, aber achten Sie auf den Speicherbedarf.
  • Achten Sie darauf, dass Sie die Materialien nicht unbeabsichtigt beschädigen. Zugriff auf Renderer.material in Skripten wird das Material dupliziert und ein Verweis auf die neue Kopie zurückgegeben. Dadurch wird eine bestehende Charge, die das Material bereits enthält, unterbrochen. Wenn Sie auf das Material des gepackten Objekts zugreifen möchten, verwenden SieRenderer.sharedMaterial stattdessen.
  • Behalten Sie die Anzahl der statischen und dynamischen Stapelaufrufe im Vergleich zur Gesamtanzahl der Zeichenaufrufe im Auge, indem Sie den Profiler oder die Rendering-Statistiken während der Optimierung verwenden.

Weitere Informationen finden Sie in der Dokumentation zur Stapelverarbeitung von Zeichnungsaufrufen.

Frame Debugger-Schnittstelle
DER FRAME DEBUGGER SCHLÜSSELT JEDEN GERENDERTEN FRAME AUF.
Prüfen Sie den Frame-Debugger

Verwenden Sie den Frame-Debugger, um die Wiedergabe auf einem einzelnen Frame einzufrieren und schrittweise zu verfolgen, wie Unity eine Szene aufbaut. Auf diese Weise können Sie Optimierungsmöglichkeiten erkennen. Suchen Sie nach GameObjects, die unnötig rendern, und deaktivieren Sie sie, um die Anzahl der Zeichenaufrufe pro Frame zu reduzieren.

Ein Hauptvorteil des Frame Debuggers ist, dass man einen Zeichenaufruf mit einem bestimmten GameObject in der Szene verbinden kann. Dies erleichtert die Untersuchung bestimmter Probleme, die in externen Frame-Debuggern möglicherweise nicht möglich sind.

Hinweis Der Frame-Debugger zeigt keine einzelnen Zeichenaufrufe oder Zustandsänderungen an. Während nur die nativen GPU-Profiler detaillierte Draw-Call- und Timing-Informationen liefern können, kann der Frame-Debugger dennoch sehr hilfreich sein, um Pipeline-Probleme oder Batching-Probleme zu beheben.

Lesen Sie die Dokumentation zum Frame-Debugger für weitere Details.

Optimieren Sie die Füllrate und reduzieren Sie Überziehungen

Die Füllrate bezieht sich auf die Anzahl der Pixel, die der Grafikprozessor pro Sekunde auf dem Bildschirm darstellen kann. Wenn Ihr Spiel durch die Füllrate begrenzt ist, bedeutet dies, dass es versucht, mehr Pixel pro Frame zu zeichnen, als der Grafikprozessor verarbeiten kann.

Das mehrfache Zeichnen über demselben Pixel wird als Überzeichnen bezeichnet. Overdraw verringert die Füllrate und kostet zusätzliche Speicherbandbreite. Die häufigsten Ursachen für eine Überziehung sind:

  • Überlappende undurchsichtige oder transparente Geometrie
  • Komplexe Shader, oft mit mehreren Renderdurchgängen
  • Nicht optimierte Partikel
  • Überlappende UI-Elemente

Auch wenn Sie die Auswirkungen minimieren sollten, gibt es kein Patentrezept für die Lösung von Überziehungen. Probieren Sie die folgenden Techniken aus, um die Auswirkungen zu verringern.

Reduzieren Sie die Anzahl der Chargen

Wie bei anderen Plattformen bedeutet die Optimierung auf Konsolen oft eine Reduzierung der Draw-Call-Batches. Hier sind einige Techniken, die helfen können:

  • verwenden Beseitigen von Verdeckungen um Objekte zu entfernen, die hinter Objekten im Vordergrund verborgen sind, und die Überzeichnung zu reduzieren. Beachten Sie, dass dies zusätzliche CPU-Verarbeitung erfordert. Verwenden Sie daher den Profiler, um zu überprüfen, ob die Verlagerung der Arbeit von der GPU auf die CPU tatsächlich von Vorteil ist.
  • GPU-Instanzierung kann auch Ihre Stapel reduzieren, wenn Sie viele Objekte haben, die dasselbe Mesh und Material verwenden. Die Begrenzung der Anzahl der Modelle in Ihrer Szene kann die Leistung verbessern. Wenn man es geschickt anstellt, kann man eine komplexe Szene aufbauen, ohne dass sie repetitiv wirkt.
  • Der SRP Batcher kann die GPU-Einrichtung zwischen Zeichnungsaufrufen reduzieren, indem er GPU-Befehle zum Binden und Zeichnen zusammenfasst. Um von diesem SRP-Batching zu profitieren, verwenden Sie so viele Materialien wie nötig, aber beschränken Sie sie auf eine kleine Anzahl kompatibler Shader (z. B. Beleuchtet- und Unbeleuchtet-Shader in URP und HDRP).
Occlusion Culling-Interface
EIN BEISPIEL FÜR OCCLUSION CULLING.
Achten Sie auf die Keulung

Das Culling findet für jede Kamera statt und kann sich stark auf die Leistung auswirken, insbesondere wenn mehrere Kameras gleichzeitig aktiviert sind. Unity verwendet zwei Arten von Culling:

  • Das Frustum Culling wird bei jeder Kamera automatisch durchgeführt. Es stellt sicher, dass GameObjects außerhalb der Ansicht Frustum nicht gerendert werden, um Leistung zu sparen.
  • Sie können die Abstände für die einzelnen Ebenen manuell über Camera.layerCullDistances festlegen. Damit können Sie kleine GameObjects in einem kürzeren Abstand als der StandardfarClipPlane Eigenschaft. Organisieren Sie dazu die Spielobjekte in Layern. Verwenden Sie das Array .layerCullDistances, um jeder der 32 Ebenen einen Wert zuzuweisen, der kleiner als die farClipPlane ist (oder verwenden Sie 0, um die farClipPlane als Standard zu verwenden).
  • Unity geht zuerst schichtweise vor. Sie behält nur die GameObjects auf den Ebenen, die die Kamera verwendet. Danach werden durch das Frustum-Culling alle GameObjects außerhalb des Kamerafrustums entfernt.
  • Das Frustum-Culling wird in Form einer Reihe von Aufträgen durchgeführt, die die verfügbaren Worker-Threads nutzen. Jeder Ebenentest ist schnell erledigt (im Grunde nur eine Bitmaskenoperation). Bei einer großen Anzahl von Spielobjekten können sich diese Kosten jedoch summieren. Wenn dies zu einem Problem für Ihr Projekt wird, müssen Sie möglicherweise ein System implementieren, um Ihre Welt in "Sektoren" zu unterteilen und Sektoren zu deaktivieren, die außerhalb des Kamera-Frustums liegen, um das Layer/Frustum-Culling-System von Unity zu entlasten.
  • Occlusion Culling entfernt alle GameObjects aus der Game-Ansicht, wenn die Kamera sie nicht sehen kann. Objekte, die hinter anderen Objekten verborgen sind, können möglicherweise noch gerendert werden und Ressourcen kosten. Verwenden Sie Occlusion Culling, um sie zu verwerfen.
  • Das Rendern eines Raums ist zum Beispiel unnötig, wenn eine Tür geschlossen ist und die Kamera nicht in den Raum hineinsehen kann. Wenn Sie Occlusion Culling aktivieren, kann dies die Leistung erheblich steigern, aber auch mehr Speicherplatz, CPU-Zeit und RAM verbrauchen. Unity backt die Occlusion-Daten während des Builds und muss sie dann beim Laden einer Szene von der Festplatte in den RAM laden.
  • Während das Frustum-Culling außerhalb der Kameraansicht automatisch erfolgt, ist das Occlusion-Culling ein Baked-Prozess. Markieren Sie Ihre Objekte einfach als statisch, verdeckt oder verdeckt und backen Sie sie dann über das Dialogfeld Fenster > Rendering > Verdeckungen entfernen.

Mehr dazu erfahren Sie im Tutorial Arbeiten mit Occlusion Culling.

Nutzung der dynamischen Auflösung

Mit der Einstellung Dynamische Auflösung der Kamera zulassen können Sie einzelne Rendering-Ziele dynamisch skalieren, um die Arbeitsbelastung des Grafikprozessors zu verringern. In Fällen, in denen sich die Bildrate der Anwendung verringert, können Sie die Auflösung schrittweise herabsetzen, um eine gleichbleibende Bildrate zu erhalten.

Unity löst diese Skalierung aus, wenn die Leistungsdaten darauf hindeuten, dass die Framerate aufgrund der GPU-Bindung abzunehmen droht. Sie können diese Skalierung auch vorab manuell mit einem Skript auslösen. Dies ist nützlich, wenn Sie sich einem GPU-intensiven Abschnitt der Anwendung nähern. Bei stufenweiser Skalierung kann die dynamische Auflösung fast unmerklich sein.

Eine Liste der unterstützten Plattformen finden Sie auf der Handbuchseite zur dynamischen Auflösung.

Camera Stacking-Demo
KAMERASTAPELUNG IN URAP: DIE WAFFE UND DER HINTERGRUND WERDEN MIT VERSCHIEDENEN KAMERAEINSTELLUNGEN GERENDERT.
Mehrere Kameraansichten prüfen

Manchmal muss man während des Spiels aus mehr als einem Blickwinkel rendern. In Ego-Shootern (FPS) ist es zum Beispiel üblich, die Waffe des Spielers und die Umgebung getrennt mit unterschiedlichen Sichtfeldern (FOV) zu zeichnen. Dadurch wird verhindert, dass die Objekte im Vordergrund durch das Weitwinkel-FOV des Hintergrunds verzerrt erscheinen.

Sie können verwenden Kamera-Stapelung in URP verwenden, um mehr als eine Kameraansicht zu rendern. Für jede Kamera wird jedoch noch ein erheblicher Teil der Daten bereinigt und gerendert. Jede Kamera verursacht einen gewissen Overhead, unabhängig davon, ob sie sinnvolle Arbeit leistet oder nicht.

Verwenden Sie nur Kamerakomponenten, die für das Rendering erforderlich sind. Auf mobilen Plattformen kann jede aktive Kamera bis zu 1 ms CPU-Zeit beanspruchen, selbst wenn nichts gerendert wird.

Detaillierungsgrad verwenden

Wenn sich Objekte in die Ferne bewegen, kann die Detailgenauigkeit (LOD) angepasst oder umgeschaltet werden, um Meshes mit geringerer Auflösung und einfacheren Materialien und Shadern zu verwenden. Dadurch wird die GPU-Leistung verbessert.

Im Kurs Arbeiten mit LODs auf Unity Learn finden Sie weitere Details.

Nachbearbeitungsschnittstelle
HALTEN SIE NACHBEARBEITUNGSEFFEKTE SO EINFACH WIE MÖGLICH.
Profil-Nachbearbeitungseffekte

Erstellen Sie ein Profil Ihrer Nachbearbeitungseffekte, um deren Kosten für den Grafikprozessor zu ermitteln. Einige Vollbild-Effekte, wie Bloom und Tiefenschärfe, können teuer sein. Es lohnt sich also zu experimentieren, bis Sie das gewünschte Gleichgewicht zwischen visueller Qualität und Leistung gefunden haben.

Die Nachbearbeitung unterliegt während der Laufzeit keinen großen Schwankungen. Sobald Sie Ihre Volumenüberschreibungen festgelegt haben, weisen Sie den Nachbearbeitungseffekten einen statischen Anteil Ihres gesamten Bildbudgets zu.

Tessellationsshader vermeiden

Bei der Tesselierung wird eine Form in kleinere Versionen ihrer selbst unterteilt, was die Detailgenauigkeit durch eine verbesserte Geometrie erhöhen kann. Obwohl es Beispiele gibt, bei denen Tessellation am meisten Sinn macht, wie z. B. die Baumrinde in der Unity-Demo Book of the Dead, sollte man Tessellation auf Konsolen vermeiden, da sie die GPU stark belastet.

Lesen Sie hier mehr über die Totenbuch-Demo.

Ersetzen Sie Geometrie-Shader durch Compute-Shader

Wie Tessellationsshader können Geometrie- und Vertex-Shader zweimal pro Frame auf der GPU ausgeführt werden - einmal während des Tiefen-Prepasses und ein zweites Mal während des Schattenpasses.

Wenn Sie Scheitelpunktdaten auf dem Grafikprozessor erzeugen oder ändern wollen, ist ein Compute-Shader oft die bessere Wahl, insbesondere im Vergleich zu einem Geometrie-Shader. Die Arbeit in einem Compute-Shader zu erledigen bedeutet, dass der Vertex-Shader, der die Geometrie tatsächlich rendert, viel schneller arbeiten kann.

Erfahren Sie mehr über Shader-Kernkonzepte.

Graphen der guten und schlechten Wellenfrontbelegung
GUTE UND SCHLECHTE WELLENFRONTBELEGUNG
Anstreben einer guten Wellenfrontbelegung

Wenn Sie einen Zeichenaufruf an die GPU senden, wird diese Arbeit in viele Wellenfronten aufgeteilt, die Unity auf die verfügbaren SIMDs innerhalb der GPU verteilt. Jede SIMD hat eine maximale Anzahl von Wellenfronten, die gleichzeitig ausgeführt werden können.

Die Wellenfrontenbelegung gibt an, wie viele Wellenfronten im Verhältnis zum Maximum derzeit genutzt werden. Er misst, wie gut Sie das Potenzial der GPU nutzen. Die Profiling-Tools für die Konsolenentwicklung zeigen die Wellenfrontbelegung sehr detailliert an.

Im obigen Beispiel aus Unitys Book of the Dead erscheinen Vertex-Shader-Wellenfronten in Grün und Pixel-Shader-Wellenfronten in Blau. Im unteren Diagramm erscheinen viele Vertex-Shader-Wellenfronten ohne viel Pixel-Shader-Aktivität. Dies zeigt eine unzureichende Auslastung der GPU.

Wenn Sie viel Vertex-Shader-Arbeit leisten, die nicht in Pixeln resultiert, könnte das auf eine Ineffizienz hinweisen. Eine niedrige Wellenfrontauslastung ist zwar nicht unbedingt schlecht, aber sie ist eine Kennzahl, mit der Sie beginnen können, Ihre Shader zu optimieren und nach anderen Engpässen zu suchen. Wenn Sie beispielsweise aufgrund von Speicher- oder Rechenoperationen ins Stocken geraten, kann eine höhere Auslastung die Leistung verbessern. Andererseits können zu viele Wellenfronten im Flug zu Cache-Thrashing und Leistungseinbußen führen.

Asynchrones Rechnen nutzen

Wenn Sie Intervalle haben, in denen die GPU nicht voll ausgelastet ist, können Sie die asynchrone Berechnung nutzen, um die Arbeit der Compute-Shader parallel zu Ihrer Grafikwarteschlange zu verschieben. Bei der Erstellung von Schattenkarten führt die GPU beispielsweise ein reines Tiefen-Rendering durch. Zu diesem Zeitpunkt findet nur sehr wenig Pixel-Shader-Arbeit statt und viele Wellenfronten bleiben unbesetzt.

Wenn Sie einen Teil der Compute-Shader-Arbeiten mit dem reinen Tiefen-Rendering synchronisieren können, führt dies zu einer besseren Gesamtnutzung der GPU. Die ungenutzten Wellenfronten können bei Screen Space Ambient Occlusion (SSAO ) oder anderen Aufgaben helfen, die die aktuelle Arbeit ergänzen.

Sehen Sie sich diese Sitzung über die Optimierung der Leistung für High-End-Konsolen von Unite an.

Einheitsschlüssel Art 21 11
Holen Sie sich das kostenlose E-Book

Einer unserer umfassendsten Leitfäden aller Zeiten enthält über 80 umsetzbare Tipps zur Optimierung Ihrer Spiele für PC und Konsole. Diese ausführlichen Tipps wurden von unseren Experten von Success und Accelerate Solutions erstellt und helfen Ihnen, das Beste aus Unity herauszuholen und die Leistung Ihres Spiels zu steigern.

Haben Ihnen diese Inhalte gefallen?