Diese Seite enthält Leitfäden und Best Practices zur Optimierung der mobilen Performance bei gleichzeitiger Erzielung der bestmöglichen Wiedergabetreue mit den Mobilen HDR-Funktionen. Diese umfassen Folgendes:
Informationen darüber, welche Faktoren zu Ihrem Performance-Budget auf Mobilgeräten beitragen
Best Practices für die Paketierung von Projekten mit aktivierten Mobilen HDR-Funktionen
Ein Walkthrough über die verfügbaren Werkzeuge zur Ermittlung von Performance-Engpässen in Ihren Unreal Engine Anwendungen
Die folgenden Links enthalten hilfreiche Informationen zu allgemein Performance-Themen auf Android:
Kennen Sie Ihr Performance-Budget
Das Zielgerät für Ihre Anwendung verfügt über eine begrenzte Menge an Ressourcen, sowohl für die Speicherung von Objekten im Arbeitsspeicher als auch für deren Verarbeitung. Beim Erstellen Ihrer Anwendung müssen Sie entscheiden, wofür Sie diese Ressourcen einsetzen möchten. Sie sollten sich mit den Performance-Merkmalen Ihres Geräts in Bezug auf Geschwindigkeit, Threads und Bandbreite für Ihre CPU und GPU sowie mit dem Arbeitsspeicher, dem Grafikspeicher und dem verfügbaren Speicherplatz Ihres Geräts vertraut machen.
Sie sollten Ihr Gerät auch einem Benchmark-Test unterziehen, um zu verstehen, wie es läuft und wo es zu Performance-Engpässen kommen kann. Sie können ein Gerät benchmarken, indem Sie eine anspruchsvolle Anwendung oder Tech-Demo darauf ausführen und anschließend die Performance-Statistiken beobachten.
Konsolenbefehle zum Anzeigen von Performance-Statistiken
Sie könnent Performance-Statistiken mit einer Reihe von Konsolenbefehlen prüfen. Um die Entwicklerkonsole auf einem Mobilgerät zu öffnen, berühren Sie den Bildschirm gleichzeitig mit vier Fingern. Dadurch wird eine Bildschirmtastatur und eine Eingabeaufforderung geöffnet, in die Sie Konsolenbefehle eingeben können.
Die Konsole und der Vier-Finger-Tipp-Befehl sind nur in Entwicklungs-Builds verfügbar. Sie ist nicht in den Bereichen Auslieferung oder Testen verfügbar.
Sie können innerhalb der Konsole Befehle eingeben, um Debug-Informationen auf dem Bildschirm anzuzeigen. Die folgende Tabelle enthält eine Liste von Befehlen, die Performance-Informationen bereitstellen:
| Befehl | Beschreibung |
|---|---|
GPU-Statistik | Zeigt die Zeit in Millisekunden an, die die GPU für verschiedene Prozesse benötigt. Einige Geräte, auf denen Vulkan läuft, unterstützen möglicherweise GPU-Statistiken, aber auf den meisten Mobilgeräten wird dies nicht direkt unterstützt. |
Statistik Einheit | Zeigt die Zeit in Millisekunden an, die die CPU für verschiedene Prozesse benötigt. Zeigt auch den Spiel-Thread, den Rendering-Thread und die GPU-Zeiten an. |
Statistik UnitGraph | Zeigt ein Diagramm an, das die CPU- und GPU-Auslastung im Zeitverlauf darstellt. Das kann beim Erkennen von Spitzen hilfreich sein. |
Statistik TextureGroup | Zeigt die von verschiedenen Texturpools belegte Speichermenge an. |
Weitere Konsolenbefehle, mit denen Sie die Leistung Ihrer Anwendung auf dem Gerät analysieren können, finden Sie unter Statistikbefehle.
Allgemeine Performance-Faktoren
Nachdem Sie nun wissen, wo Sie die Performance-Daten auf Ihrem Gerät finden, werden Sie in diesem Abschnitt mit den Faktoren vertraut gemacht, die die Performance in den mobilen Renderern von Unreal Engine am häufigsten beeinflussen. Wenn Sie verstehen, welche dieser Elemente sich auf Ihre Anwendung auswirken und wie, können Sie Probleme mithilfe der Diagnosewerkzeugen von Unreal Engine schnell identifizieren und beheben.
Normal-Maps vs. High-Scheitelpunkt-Meshs
Die mobilen Renderer von Unreal Engine sind effizient beim Rendering großer Mengen von Scheitelpunkten, während hochwertige Normal-Maps auf mobilen Renderern Probleme mit der Bittiefe haben können und einen höheren Performance-Aufwand verursachen als ein Modell mit High-Polygonanzahl.
Auf leistungsschwächeren Hardwarekomponenten können Normal-Maps die Qualität von Reflexionen und Beleuchtung auf der Oberfläche eines Modells erheblich verbessern. Allerdings können subtile Formen wie Karosserieteile eines Autos die normalerweise für diese Karten verwendeten 8-Bit-Deltas überschreiten, was zu sichtbaren Bänderung im endgültigen Rendering führt.
Sie können 16-Bit-Normal-Maps verwenden, um dies auszugleichen, aber die Pixelkosten für 16-Bit-Normalen übersteigen die Scheitelpunktkosten eines Meshs mit höherer Dichte. 16-Bit-Normalen werden in der Engine nicht komprimiert, was bedeutet, dass sie auch achtmal so groß sind wie eine reguläre Normal-Map.
Im folgenden Beispiel verwenden wir Karosserieteilemit mit hoher Auflösung ohne Normal-Maps. Bei der Ausrichtung auf das Galaxy Tab S6 umfassen unsere Karosserieteile insgesamt etwa 500.000 Scheitelpunkte.
Best Practices für Normal-Maps mit hoher Auflösung
Das Baking Scheitelpunkte mit hoher Auflösung in einer Normal-Map für ein Low-Poly-Modell kann ein komplexer Prozess sein, und viele Faktoren können die Qualität einer Normal-Map-Textur beeinträchtigen, bis sie in die Engine geladen wird. Es gibt viele Werkzeugsets für das Baking von Normal-Maps, wir empfehlen aber xNormal. Der Prozess, den wir für xNormal verwenden, läuft in etwa wie folgt ab:
Baken Sie die Normal-Map in xNormal als 8k-TIFF mit 4xAA.
Importieren Sie die TIFF-Datei in Photoshop und reduzieren Sie sie dann auf eine 1k-Textur.
Wenden Sie einen Gaußschen Weichzeichner mit einem Wert von .35px an.
Konvertieren Sie das Bild von 16 Bit in 8 Bit.
Exportieren Sie das Bild als 24-Bit-TGA.
Importieren Sie die endgültige Normal-Map in Unreal.
Um sicherzustellen, dass die im Baking-Prozess verwendeten Oberflächennormalen mit denen im Engine übereinstimmen, sollten Sie die optimierten Normalen aus Unreal exportieren. Importieren Sie das Baking-Modell in Unreal, wählen Sie die Option zum Erstellen eigener Normalen und exportieren Sie das Baking-Modell dann aus Unreal, um es in xNormal zu baken. Dies ist ein wichtiger Schritt bei der Erstellung hochwertiger Normal-Maps, da xNormal die Oberflächennormalen des Meshs kennen muss, um die Versätze aus dem Modell mit hoher Auflösung anzuwenden.
Zuletzt gibt es zwei Optionen, die Artefakte beim Rendering von statischen Meshs reduzieren:
Verwenden Sie UVs mit voller Präzision
Verwenden Sie eine Tangentenbasis mit hoher Präzision.
Beide Einstellungen sind im Statisches Mesh Editor im Details Panel unter den LODs verfügbar.
Draw-Aufruf
Draw-Aufrufe sind Abfragen nach Assets, die in jedem Frame stattfinden. Die Anzahl der Draw-Aufrufe, die Ihre Anwendung verwendet, hängt von der Anzahl der eindeutigen Meshs in Ihrer Szene sowie von der Anzahl der eindeutigen Material-IDs ab, die jedes Mesh verwendet. Derzeit sind eine hohe Anzahl von Draw-Aufrufe der größte Faktor für eine geringe Grafik-Performance, und Sie sollten diese so weit wie möglich reduzieren.
Als Beispiel könnte ein hochoptimiertes Automodell nur fünf oder sechs separate Meshs haben, und jede dieser Komponenten könnte nur ein einziges Material haben.
Ein gutes Ziel für Draw-Aufrufe in einer optimierten Szene liegt bei etwa 700 auf einem Galaxy Tab S6 und unter 500 auf weniger leistungsstarker Hardware. Bei Projekten für HMI, bei denen in der Regel sehr spezielle oder komplexe Materialien zum Einsatz kommen, wären 100 Draw-Aufrufe auf einem Galaxy Tab S6 ein gutes Ziel, während weniger als 50 vorzuziehen wären.
Sie können die Anzahl Ihrer Draw-Aufrufe mit dem Konsolenbefehl Stat RHI ausgeben.
Beachten Sie, dass sich die Anzahl der Draw-Aufrufe je nachdem, ob Sie sich in PIE oder auf dem Gerät befinden, ändert. |
Mesh-Anzahl reduzieren
Der einfachste Weg, die Anzahl der Draw-Aufrufe zu reduzieren, ist, die Anzahl der einzigartigen Meshs in Ihrer Welt zu verringern. Sie können dies tun, indem Sie so viele Objekte wie möglich mit einem Werkzeugsatz zur Erstellung digitaler Inhalte (DCC) wie Maya, 3DSMax oder Blender zu einem einzigen Mesh zusammenfassen, bevor Sie sie in Unreal importieren.
Material-ID-Anzahl reduzieren
Es gibt mehrere Optionen, die Anzahl der einzigartigen Materialien auf einem Mesh zu reduzieren.
Die einfachste Methode ist die Verwendung eines Programms wie Substance Painter, das mehrere Materialien in derselben Textur integriert. Dadurch können Sie eine Vielzahl von Materialtypen in einem sehr einfachen Unreal-Material nutzen, das Sie dann als Grundlage für Material-Instanzen mit einfachen Textureingaben verwenden können. Dies kann auch die Anzahl der Materialanweisungen reduzieren, was die Performance weiter verbessert.
Die zweite Methode verwendet Maskierung für einen mehr prozeduralen Ansatz. Materialien können bestimmte Charakteristiken einer Oberfläche bezeichnen, wie Farbe, Rauheit oder metallische Eigenschaften. Anstatt für verschiedene Teile eines Meshs unterschiedliche Materialien zu verwenden, können Sie Masken einsetzen, um Teile der UVs eines Meshs zu trennen und auf jeden Abschnitt unterschiedliche Einstellungen anzuwenden. Sie können eine einfache Maske mit einer Schwarz-Weiß-Textur erstellen, aber es ist effizienter, die Scheitelpunkt-Farbe zu verwenden.
Im folgenden Beispiel werden Scheitelpunkt-farben verwendet, um verschiedene Materialtypen zu definieren, und das Material definiert Parameter, die das Aussehen dieser Teile individuell beeinflussen können. Die Scheitelpunkt-Farbmaskierung ist effizienter und sorgt für eine schärfere Trennung, da sie nicht von der Texturauflösung abhängig ist.
Materialien
Materialkomplexität kann die Pixel-Kosten eines Renderns erhöhen. Je mehr Anweisungen für jedes Pixel vorhanden sind, desto mehr Zeit benötigt der Renderer, um dessen endgültigen Wert zu berechnen. Undurchsichtige Materialien sind am kostengünstigsten, können jedoch basierend auf dem Schattierungsmodell oder Basis-Shader-Code stark variieren.
Sie finden eine Anzeige der Anzahl der Befehle eines Materials im Fenster Statistiken im Material-Editor.
Die Anzahl der Befehle erhöht sich auch in Abhängigkeit von der Anzahl der mathematischen Funktionen, die in einem Material vorhanden sind. Je mehr Knotenpunkte vorhanden sind, desto aufwendiger wird das Rendern des Materials. Einige spezifische Operationen sind auch mit höheren Kosten verbunden. Versuchen Sie, die Anzahl der Befehle zu begrenzen, wenn Sie komplexere Materialien erstellen.
Durchscheinende und transparente Materialien gehören zu den teuersten Materialarten. Einzelne Transluzenzschichten verursachen hohe Kosten pro Pixel, und wenn mehrere Transparenzschichten übereinandergelegt und gerendert werden, sind die Kosten noch viel höher. Das wird als Überziehen bezeichnet.
Scheinwerfer und Rückleuchten für Fahrzeuge sind Beispiele für Problembereiche mit Transparenz. In vielen Fällen verwenden wir stattdessen handgemalte Textur-Maps, um die Materialkomplexität zu reduzieren. Komplexe Formen und Tiefen lassen sich auch mit einer flachen Textur gut darstellen.
Optimieren der Texturauflösung
Hochauflösende Texturen benötigen viel Speicherplatz, sowohl auf dem Gerät als auch im Texturspeicher des Geräts, und größere Texturen erfordern mehr Pixel für die Darstellung und Verarbeitung. Obwohl sie die Wiedergabetreue verbessern können, nimmt der Nutzen der Texturgröße angesichts der Bildschirmauflösung Ihres Geräts und des Betrachtungswinkels der Textur ab. Es ist wichtig, die kleinste mögliche Textur zu verwenden, um den gewünschten Level an Wiedergabetreue zu erzielen.
Um Ihre Texturanforderungen zu bestimmen, müssen Sie zunächst die Kameraposition und das Sichtfeld (FOV) festlegen, aus dem Sie Ihr Modell betrachten möchten. Dies hilft dabei, den Bildschirmraum aller Meshs und Materialien zu bestimmen.
Sobald die Position einer Kamera festgelegt ist, können Sie mithilfe einer speziellen Debug-Textur die Texturauflösung bestimmen, die für die verschiedenen Materialien verwendet werden soll. Diese Textur nutzt das Verhalten von Mip-Maps, um zu bestimmen, welche Auflösung für verschiedene Komponenten erforderlich ist, und wendet dabei in jeder Mip-Map unterschiedliche Farben an. So kann leicht erkannt werden, welchen Mip das Material verwendet und welche Textur-Auflösung benutzt werden sollte.
Fügen Sie die mitgelieferte Textur in den Emissiven Kanal eines unbeleuchteten Materials ein und wenden Sie dieses Material dann auf Ihr Mesh an. Wenn Sie das Mesh aus der richtigen Kameraentfernung betrachten, zeigt die Farbkodierung an, welchen Mip-Level die Engine zum Rendern verwendet. Der höchste beobachtete Level sollte die native Texturgröße Ihrer Normal- und Umgebungsverdeckung-Karten sein.
Paketgröße und Startzeit
Bei der Paketierung einer Anwendung und ihrer Assets muss ein Kompromiss zwischen der Paketgröße auf der Festplatte und der Start-Performance zur Laufzeit gefunden werden.
Wenn die ZLib-Komprimierung aktiviert ist, wird die Paketgröße Ihrer Anwendung kleiner. Dies erfordert jedoch mehr CPU-Zeit zum Laden der Anwendung, was die Startgeschwindigkeit verlangsamen kann. Für eine optimale Startzeit können Sie die Komprimierung deaktivieren.
Empfohlene Streaming-Einstellungen
Die folgenden Streaming-Einstellungen werden in der DefaultEngine.ini empfohlen. Sie bieten beim Start einer Anwendung zusätzliche Zeit für das asynchrone Laden von Assets, wodurch die Startzeit verbessert werden kann.
[/Script/Engine.StreamingSettings]
s.PriorityAsyncLoadingExtraTime=275.0
s.LevelStreamingActorsUpdateTimeLimit=250.0
s.PriorityLevelStreamingActorsUpdateExtraTime=250.0Empfohlene Paketierungs-Einstellungen
Die folgenden Paketierungs-Einstellungen werden in der DefaultEngine.ini empfohlen. Diese Einstellungen reduzieren die Komprimierungsrate bei der Paketierung von Assets, da unkomprimierte .pak Dateien beim Start deutlich schneller geladen werden als mit ZLib komprimierte Dateien.
[/Script/UnrealEd.ProjectPackagingSettings]
bCompressed=False
BuildConfiguration=PPBC_Development
bShareMaterialShaderCode=True
bSharedMaterialNativeLibraries=True
bSkipEditorContent=TrueAnalyse der Paketgröße auf der Festplatte
Die Unreal Engine verfügt über mehrere nützliche Werkzeuge, die einen Einblick in den Daten-Footprint von Assets bieten können.
Größenkarte
Die Größenkarte liest und vergleicht den relativen Speicherverbrauch von Assets im Editor. Um es zu verwenden, müssen Sie das Plugin AssetManagerEditor aktivieren. Danach können Sie darauf zugreifen, indem Sie mit der rechten Maustaste auf einen Ordner im Inhaltsbrowser klicken und im Kontextmenü Größenkarte auswählen.
Die Größenkarte zeigt ein Fenster mit Symbolen an, die die von Ordnern und Dateien belegte Speichermenge darstellen. Je größer das Symbol, desto mehr Speicherplatz benötigt eine Datei.
Weitere Informationen zur Verwendung der Größenkarte finden Sie unter Cooking und Chunking.
Die Größenkarte liest den Footprint von Assets, während diese im Editor verwendet werden. Nachdem Sie Ihr Projekt gepackt haben, wird sich der Speicherverbrauch ändern. Dies ist auf die verschiedenen Arten der Komprimierung zurückzuführen, die während des Cook-Prozess auftreten. Als Faustregel gilt, dass die Größenkarte die größtmögliche Größe darstellt, die ein Asset einnehmen kann.
Statistiken
Das Werkzeug Statistiken bietet detailliertere Informationen zur Verwendung von Assets innerhalb eines Levels. Sie finden es im Fenster-Dropdown-Menü.
Das Statistikfenster schlüsselt die Anzahl der Assets in Ihren Level-Dateien auf und kann entweder alle Levels oder nur bestimmte Levels anzeigen. Grundkörper Statistiken listet Informationen über die Anzahl der Dreiecke, den Speicherverbrauch und die Anzahl auf.
Andere in dieser Liste angezeigte Daten umfassen Informationen zur Texturverwendung und zur Beleuchtung statischer Meshs. Der Listenmodus des Statistikfensters kann schnell veranschaulichen, welche Assets den meisten Speicherplatz belegen. Die Daten unter Cooker-Statistiken sind ebenfalls äußerst nützlich, da sie alle Assets auflisten, die im letzten Paketierungsprozess gecookt wurden.
Speicherberichte
Während die Werkzeuge Statistiken- und Größenkarte Ihnen den Daten-Footprint Ihrer Dateien im Unreal Editor anzeigen, kann der Konsolenbefehl Memreport -full von einer Installation Ihrer Anwendung verwendet werden, die auf einem Zielgerät gestartet wurde. Dies bietet einen detaillierten und genauen Überblick über die Größe Ihrer Dateien, wie sie mit den Komprimierungseinstellungen Ihres Geräts vorliegen werden.
Sobald die App in der Entwicklungskonfiguration erstellt und auf das Gerät geladen wurde, können Sie das Konsolenfenster öffnen und den Befehl eingeben. Dieser Speicher-Schnappschuss wird im Projektverzeichnis auf dem Gerät gespeichert. Das Verzeichnis lautet in der Regel Game/[YourApp]/[YourApp]/Saved/Profiling/Memreports/, kann jedoch variieren.
Die Datei .memreport ist eine Textdatei, die mit den meisten Texteditoren geöffnet werden kann. Der Anfang des Textes enthält einige Informationen über den zugewiesenen Speicher und die Poolgrößen, während der Großteil des Textes eine Aufzeichnung der geladenen Levels, RHI-Statistiken, Renderziele, Szeneninformationen und mehr enthält. Alle diese Informationen sind wertvoll, da sie die tatsächlichen Daten darstellen, die den Cooking- und Paketierungs-Prozess durchlaufen haben.
Wenn Sie nach dem Begriff Auflistung aller Texturen suchen, finden Sie eine Liste aller Texturen in Ihrer Anwendung sowie detaillierte Informationen zum Texturtyp, zur Gruppe, zur Größe und zum Speicher-Footprint. Die Liste ist nach Speichergröße sortiert, wobei größere Texturen zuerst angezeigt werden. Dies ist eine schnelle und einfache Methode, um festzustellen, welche Texturen den meisten Speicherplatz beanspruchen.
Analyse der Startzeit
Die Faktoren, die die Startzeit beeinflussen, umfassen Folgendes:
Die Zeit, die zum Laden und Dekomprimieren der anfänglichen Assets benötigt wird
Die Gesamtgröße Ihrer Anwendung
Alle Plugins, die in der Installation Ihres Benutzers aktiviert werden müssen
Die Menge der zu parsenden String-Daten
Jegliche Speicherzuweisung oder Fragmentierung auf dem Gerät des Benutzers
Es gibt verschiedene Werkzeuge zur Analyse der Startzeit Ihrer Anwendung, aber Unreal Insights ist das empfehlenswerteste, da es Performance-Daten von einem Zielgerät aus der Ferne profilieren kann. Ausführliche Informationen zu diesem Werkzeugsatz finden Sie im Unreal Insights Abschnitt.
Ein Beispiel für die Verwendung von Unreal Insights in einer Android-Anwendung finden Sie unter