Optimieren Sie die Leistung Ihres Mobilspiels: Experten-Tipps zu Grafiken und Assets

Unser integriertes Erfolgsteam unterstützt Unity-Kunden bei ihren komplexen technischen Problemen. Wir haben uns mit diesem Team von Senior Software Engineers zusammengesetzt und sie gebeten, ihr Fachwissen zur Optimierung von Mobilspielen zu teilen.
Unser Unity Studio Production Team kennt den Quellcode in- und auswendig und arbeitet mit einer Vielzahl von Unity-Kunden zusammen, um ihnen zu helfen, das Beste aus der Engine herauszuholen. In ihrer Arbeit tauchen sie tief in die Projekte der Ersteller ein, um Punkte zu identifizieren, an denen die Leistung für mehr Geschwindigkeit, Stabilität und Effizienz optimiert werden kann. Als unsere Ingenieure begannen, ihre Erkenntnisse zur Optimierung von Mobilspielen zu teilen, wurde uns ziemlich schnell klar, dass es viel zu viele großartige Informationen für den einzelnen Blogbeitrag gab, den wir geplant hatten. Stattdessen haben wir beschlossen, ihr Wissen in ein umfassendes E-Book (das Sie hier herunterladen können) sowie in eine Reihe von Blogbeiträgen zu verwandeln, die einige dieser 75+ umsetzbaren Tipps hervorheben.
Im letzten Teil dieser Optimierungsreihe konzentrieren wir uns darauf, wie Sie die Leistung Ihrer Assets, Projektkonfiguration und Grafiken verbessern können. Falls Sie sie verpasst haben, schauen Sie sich unsere vorherigen Beiträge zu Profiling, Speicher und Codearchitektur sowie Physik, UI und Audio an, um ein vollständigeres Bild davon zu erhalten, wie Sie Ihr Spiel optimieren können – oder laden Sie das kostenlose E-Book für eine Zusammenfassung all dieser Themen herunter.
Es gibt einige Projekteinstellungen, die Ihre mobile Leistung beeinflussen können.
Reduzieren oder Deaktivieren der Beschleunigerfrequenz
Unity greift mehrmals pro Sekunde auf den Beschleuniger Ihres Mobilgeräts zu. Deaktivieren Sie dies, wenn es in Ihrer Anwendung nicht verwendet wird, oder reduzieren Sie die Frequenz für eine bessere Leistung.

Deaktivieren Sie unnötige Spieler- oder Qualitätseinstellungen
In den Player-Einstellungen deaktivieren Sie Auto Graphics API für nicht unterstützte Plattformen, um die Erzeugung übermäßiger Shader-Varianten zu verhindern. Deaktivieren Sie Zielarchitekturen für ältere CPUs, wenn Ihre Anwendung diese nicht unterstützt.
In den Qualität-Einstellungen deaktivieren Sie unnötige Qualitätsstufen.
Deaktiviere unnötige Physik
Wenn dein Spiel keine Physik verwendet, deaktiviere Auto-Simulation und Auto-Synchronisierung von Transformen. Diese werden deine Anwendung nur verlangsamen, ohne erkennbare Vorteile.
Wähle die richtige Bildrate
Mobile Projekte müssen Bildraten mit Akkulaufzeit und thermischer Drosselung ausbalancieren. Anstatt die Grenzen deines Geräts bei 60 fps zu überschreiten, ziehe in Betracht, mit 30 fps als Kompromiss zu arbeiten. Unity verwendet standardmäßig 30 fps für mobile Geräte.
Du kannst die Bildrate auch während der Laufzeit dynamisch mit Application.targetFrameRate anpassen. Zum Beispiel könntest du unter 30 fps fallen für langsame oder relativ statische Szenen und höhere fps-Einstellungen für das Gameplay reservieren.
Vermeide große Hierarchien
Teile deine Hierarchien auf. Wenn deine GameObjects nicht in einer Hierarchie geschachtelt sein müssen, vereinfache die Elternschaft. Kleinere Hierarchien profitieren von Multithreading, um die Transformationsdaten in deiner Szene zu aktualisieren. Komplexe Hierarchien verursachen unnötige Transformationsberechnungen und höhere Kosten für die Speicherbereinigung.
Siehe Optimierung der Hierarchie und diesen Unite-Vortrag für bewährte Praktiken mit Transformen.
Transformiere einmal, nicht zweimal
Zusätzlich, wenn du Transformen bewegst, verwende Transform.SetPositionAndRotation, um sowohl Position als auch Rotation auf einmal zu aktualisieren. Dies vermeidet den Overhead, einen Transform zweimal zu ändern.
Wenn du ein GameObject zur Laufzeit instanziieren musst, ist eine einfache Optimierung, während der Instanziierung zu parenten und neu zu positionieren:
GameObject.Instantiate(prefab, parent);
GameObject.Instantiate(prefab, parent, position, rotation);
Für weitere Details zu Object.Instantiate siehe die Scripting API.
Gehe davon aus, dass Vsync aktiviert ist
Mobile Plattformen rendern keine halben Frames. Selbst wenn du Vsync im Editor (Projekteinstellungen > Qualität) deaktivierst, ist Vsync auf Hardware-Ebene aktiviert. Wenn die GPU nicht schnell genug aktualisieren kann, wird das aktuelle Frame gehalten, was effektiv deine fps reduziert.
Die Asset-Pipeline kann die Leistung deiner Anwendung erheblich beeinflussen. Ein erfahrener technischer Künstler kann deinem Team helfen, Asset-Formate, Spezifikationen und Import-Einstellungen zu definieren und durchzusetzen, um reibungslose Prozesse zu gewährleisten.
Verlasse dich nicht auf die Standardeinstellungen. Verwende die plattformspezifische Überschreibung, um Assets wie Texturen und Mesh-Geometrie zu optimieren. Falsche Einstellungen können zu größeren Build-Größen, längeren Build-Zeiten und schlechter Speichernutzung führen. Ziehe in Betracht, die Voreinstellungen Funktion zu verwenden, um Basiseinstellungen anzupassen, die ein bestimmtes Projekt verbessern.
Siehe dieses Handbuch zu Best Practices für Kunst-Assets oder schau dir diesen Kurs über 3D Kunstoptimierung für mobile Anwendungen über Unity Learn für weitere Details an.
Importiere Texturen korrekt
Der Großteil deines Speichers wird wahrscheinlich für Texturen verwendet, daher sind die Import-Einstellungen hier entscheidend. Versuche im Allgemeinen, diese Richtlinien zu befolgen:
- Reduziere die Maximalgröße: Verwende die minimalen Einstellungen, die visuell akzeptable Ergebnisse liefern. Dies ist nicht destruktiv und kann schnell deinen Texturspeicher reduzieren.
- Verwenden Sie Potenzen von zwei (POT): Unity erfordert POT-Texturgrößen für mobile Texturkomprimierungsformate (PVRCT oder ETC).
- Atlasieren Sie Ihre Texturen: Das Platzieren mehrerer Texturen in einer einzigen Textur kann die Draw Calls reduzieren und das Rendering beschleunigen. Verwenden Sie den Unity Sprite Atlas oder den Drittanbieter TexturePacker, um Ihre Texturen zu atlasieren.
- Deaktivieren Sie die Option "Read/Write Enabled": Wenn aktiviert, erstellt diese Option eine Kopie im sowohl CPU- als auch GPU-adressierbaren Speicher, wodurch der Speicherbedarf der Textur verdoppelt wird. In den meisten Fällen sollte dies deaktiviert bleiben. Wenn Sie Texturen zur Laufzeit generieren, erzwingen Sie dies über Texture2D.Apply, indem Sie makeNoLongerReadable auf true setzen.
- Deaktivieren Sie unnötige Mip Maps: Mip Maps sind für Texturen, die eine konsistente Größe auf dem Bildschirm beibehalten, wie 2D-Sprites und UI-Grafiken, nicht erforderlich (lassen Sie Mip Maps für 3D-Modelle aktiviert, die ihre Entfernung von der Kamera variieren).

Texturen komprimieren
Berücksichtigen Sie diese beiden Beispiele mit demselben Modell und derselben Textur. Die Einstellungen auf der linken Seite verbrauchen fast achtmal so viel Speicher wie die auf der rechten Seite, ohne viel Vorteil in der visuellen Qualität.

Verwenden Sie Adaptive Scalable Texture Compression (ATSC) sowohl für iOS als auch für Android. Die überwiegende Mehrheit der in Entwicklung befindlichen Spiele zielt auf Mindestgeräte ab, die ATSC-Komprimierung unterstützen.
Die einzigen Ausnahmen sind:
- iOS-Spiele, die auf A7-Geräte oder älter abzielen (z. B. iPhone 5, 5S usw.) – verwenden Sie PVRTC
- Android-Spiele, die auf Geräte vor 2016 abzielen – verwenden Sie ETC2 (Ericsson Texture Compression)
Wenn komprimierte Formate wie PVRTC und ETC nicht ausreichend hochqualitativ sind und wenn ASTC auf Ihrer Zielplattform nicht vollständig unterstützt wird, versuchen Sie, 16-Bit-Texturen anstelle von 32-Bit-Texturen zu verwenden.
Siehe das Handbuch für weitere Informationen zum empfohlenen Texturkomprimierungsformat nach Plattform.
Mesh-Importeinstellungen anpassen
Ähnlich wie Texturen können Meshes übermäßigen Speicher verbrauchen, wenn sie nicht sorgfältig importiert werden. Um den Speicherverbrauch von Meshes zu minimieren:
- Komprimieren Sie das Mesh: Aggressive Kompression kann den Speicherplatz reduzieren (der Speicher zur Laufzeit bleibt jedoch unbeeinflusst). Beachten Sie, dass die Quantisierung von Meshes zu Ungenauigkeiten führen kann, experimentieren Sie also mit Kompressionsstufen, um herauszufinden, was für Ihre Modelle funktioniert.
- Lesen/Schreiben deaktivieren: Wenn Sie diese Option aktivieren, wird das Mesh im Speicher dupliziert, wodurch eine Kopie des Meshs im Systemspeicher und eine andere im GPU-Speicher bleibt. In den meisten Fällen sollten Sie es deaktivieren (in Unity 2019.2 und früher ist diese Option standardmäßig aktiviert).
- Rigs und BlendShapes deaktivieren: Wenn Ihr Mesh keine Skelett- oder Blendshape-Animation benötigt, deaktivieren Sie diese Optionen, wo immer möglich.
- Normen und Tangenten deaktivieren: Wenn Sie sich absolut sicher sind, dass das Material des Meshs keine Normen oder Tangenten benötigt, deaktivieren Sie diese Optionen für zusätzliche Einsparungen.

Überprüfen Sie Ihre Polygonanzahlen
Höhere Auflösungsmodelle bedeuten mehr Speicherverbrauch und potenziell längere GPU-Zeiten. Benötigt Ihre Hintergrundgeometrie eine halbe Million Polygone? Überlegen Sie, Modelle in Ihrem bevorzugten DCC-Paket zu reduzieren. Löschen Sie unsichtbare Polygone aus dem Blickwinkel der Kamera und verwenden Sie Texturen und Normalen-Maps für feine Details anstelle von hochdichten Netzen.
Automatisieren Sie Ihre Importeinstellungen mit dem AssetPostprocessor
Der AssetPostprocessor ermöglicht es Ihnen, Skripte beim Importieren von Assets auszuführen. Dies fordert Sie auf, die Einstellungen vor und/oder nach dem Importieren von Modellen, Texturen, Audio usw. anzupassen.
Verwenden Sie das Addressable Asset System
Das Addressable Asset System bietet eine vereinfachte Möglichkeit, Ihre Inhalte zu verwalten. Dieses einheitliche System lädt AssetBundles nach "Adresse" oder Alias, asynchron von einem lokalen Pfad oder einem Remote-Content-Delivery-Netzwerk (CDN).

Wenn Sie Ihre Nicht-Code-Assets (Modelle, Texturen, Prefabs, Audio und sogar ganze Szenen) in ein AssetBundle aufteilen, können Sie sie als herunterladbare Inhalte (DLC) trennen.
Verwenden Sie dann Addressables, um einen kleineren ursprünglichen Build für Ihre mobile Anwendung zu erstellen. Cloud Content Delivery ermöglicht es Ihnen, Ihre Spielinhalte zu hosten und an die Spieler zu liefern, während sie im Spiel vorankommen.

Klicken Sie hier, um zu sehen, wie das Addressable Asset System die Verwaltung von Assets erleichtern kann.
Mit jedem Frame bestimmt Unity die Objekte, die gerendert werden müssen, und erstellt dann Draw-Calls. Ein Draw-Call ist ein Aufruf an die Grafik-API, um Objekte (z. B. ein Dreieck) zu zeichnen, während ein Batch eine Gruppe von Draw-Calls ist, die zusammen ausgeführt werden sollen.
Wenn Ihre Projekte komplexer werden, benötigen Sie eine Pipeline, die die Arbeitslast auf Ihrer GPU optimiert. DieUniversal Render Pipeline (URP) verwendet derzeit einen Single-Pass-Forward-Renderer, um hochwertige Grafiken auf Ihrer mobilen Plattform bereitzustellen (Deferred Rendering wird in zukünftigen Versionen verfügbar sein). Die gleiche physikalisch basierte Beleuchtung und Materialien von Konsolen und PCs können auch auf Ihr Telefon oder Tablet skaliert werden.
Die folgenden Richtlinien können Ihnen helfen, Ihre Grafiken zu beschleunigen.
Batchen Sie Ihre Draw-Calls
Das Batchen von Objekten, die zusammen gezeichnet werden sollen, minimiert die Zustandsänderungen, die erforderlich sind, um jedes Objekt in einem Batch zu zeichnen. Dies führt zu einer verbesserten Leistung, indem die CPU-Kosten für das Rendern von Objekten gesenkt werden. Unity kann mehrere Objekte mit verschiedenen Techniken in weniger Batches kombinieren:
- Dynamisches Batching: Für kleine Meshes kann Unity die Vertices auf der CPU gruppieren und transformieren und sie dann alle auf einmal zeichnen. Hinweis: Verwenden Sie dies nur, wenn Sie genügend Low-Poly-Meshes haben (weniger als 900 Vertex-Attribute und nicht mehr als 300 Vertices). Der dynamische Batcher wird keine Meshes größer als dies batchen, daher wird das Aktivieren Zeit der CPU verschwenden, um in jedem Frame nach kleinen Meshes zu suchen, die gebatcht werden können.
- Statisches Batching: Für nicht bewegliche Geometrie kann Unity die Draw-Calls für Meshes reduzieren, die dasselbe Material teilen. Obwohl es effizienter ist als dynamisches Batching, verwendet es mehr Speicher.
- GPU-Instanzierung: Wenn Sie eine große Anzahl identischer Objekte haben, batcht diese Technik sie effizienter durch die Nutzung von Grafik-Hardware.
- SRP-Batching: Aktivieren Sie den SRP-Batcher in Ihrem Universal Render Pipeline Asset unter Erweitert. Dies kann Ihre CPU-Renderzeiten erheblich beschleunigen, abhängig von der Szene.

Verwenden Sie den Frame-Debugger
Der Frame-Debugger zeigt, wie jeder Frame aus einzelnen Draw-Calls aufgebaut ist. Dies ist ein unschätzbares Werkzeug zur Fehlersuche Ihrer Shader-Eigenschaften, das Ihnen helfen kann, zu analysieren, wie das Spiel gerendert wird.

Neu im Frame-Debugger? Schauen Sie sich dieses Einführungstutorial hier an.
Vermeiden Sie zu viele dynamische Lichter
Es ist entscheidend, zu vermeiden, dass Sie zu viele dynamische Lichter in Ihre mobile Anwendung hinzufügen. Erwägen Sie Alternativen wie benutzerdefinierte Shader-Effekte und Lichtproben für dynamische Meshes sowie gebackenes Licht für statische Meshes.
Siehe diese Funktionsvergleichstabelle für die spezifischen Grenzen von URP und integrierten Pipeline-Echtzeitleuchten.
Schatten deaktivieren
Das Schattenwerfen kann pro MeshRenderer und Licht deaktiviert werden. Deaktivieren Sie Schatten, wann immer es möglich ist, um Draw-Calls zu reduzieren.
Sie können auch gefälschte Schatten erstellen, indem Sie eine verschwommene Textur auf ein einfaches Mesh oder Quad unter Ihren Charakteren anwenden. Andernfalls können Sie Blob-Schatten mit benutzerdefinierten Shadern erstellen.

Backen Sie Ihr Licht in Lichtkarten
Fügen Sie Ihrer statischen Geometrie mit globaler Beleuchtung (GI) dramatische Beleuchtung hinzu. Markieren Sie Objekte mit Tragen Sie zur GI bei, damit Sie qualitativ hochwertiges Licht in Form von Lichtkarten speichern können.
Gebackene Schatten und Beleuchtung können dann zur Laufzeit ohne Leistungseinbußen gerendert werden. Der progressive CPU- und GPU-Lichtmapper kann das Backen der globalen Beleuchtung beschleunigen.

Befolgen Sie die manual guide und dieser Artikel über die Optimierung der Beleuchtung für Hilfe beim Einstieg in das Lightmapping in Unity.
Verwenden Sie Lichtschichten
Für komplexe Szenen mit mehreren Lichtern trennen Sie Ihre Objekte mithilfe von Schichten und beschränken Sie den Einfluss jedes Lichts auf eine bestimmte Culling-Maske.

Verwenden Sie Lichtproben für bewegliche Objekte
Lichtproben speichern gebackene Beleuchtungsinformationen über den leeren Raum in Ihrer Szene und bieten qualitativ hochwertige Beleuchtung (sowohl direkt als auch indirekt). Sie verwenden sphärische Harmonien, die im Vergleich zu dynamischen Lichtern sehr schnell berechnet werden.

Verwenden Sie Level of Detail (LOD)
Wenn Objekte in die Ferne bewegen, kann Level of Detail sie anpassen oder auf einfachere Meshes mit einfacheren Materialien und Shadern umschalten, um die GPU-Leistung zu unterstützen.


Verwenden Sie Occlusion Culling, um versteckte Objekte zu entfernen
Objekte, die hinter anderen Objekten verborgen sind, können möglicherweise weiterhin gerendert werden und Ressourcen kosten. Verwenden Sie Occlusion Culling, um sie zu verwerfen.
Während das Frustum-Culling außerhalb der Kamerasicht automatisch erfolgt, ist das Occlusion Culling ein gebackener Prozess. Markieren Sie einfach Ihre Objekte als Statische Occluder oder Occludees, und backen Sie dann über das Fenster > Rendering > Occlusion Culling Dialogfeld. Obwohl es nicht für jede Szene notwendig ist, kann Culling in vielen Fällen die Leistung verbessern.
Schauen Sie sich das Arbeiten mit Occlusion Culling Tutorial für weitere Informationen an.
Vermeiden Sie die native Auflösung von Mobilgeräten
Da Telefone und Tablets immer fortschrittlicher werden, haben neuere Geräte tendenziell sehr hohe Auflösungen.
Verwenden Sie Screen.SetResolution(width, height, false), um die Ausgabeauflösung zu verringern und etwas Leistung zurückzugewinnen. Profilieren Sie mehrere Auflösungen, um das beste Gleichgewicht zwischen Qualität und Geschwindigkeit zu finden.
Begrenzen Sie die Verwendung von Kameras
Jede Kamera verursacht einen gewissen Overhead, unabhängig davon, ob sie sinnvolle Arbeit leistet oder nicht. Verwenden Sie nur die für das Rendering erforderlichen Kamera-Komponenten. Auf mobilen Plattformen der unteren Preisklasse kann jede Kamera bis zu 1 ms CPU-Zeit in Anspruch nehmen.
Halten Sie Shader einfach
Die Universal Render Pipeline umfasst mehrere leichte Lit- und Unlit-Shader, die bereits für mobile Plattformen optimiert sind. Versuchen Sie, die Variationen Ihrer Shader so gering wie möglich zu halten, da sie einen dramatischen Einfluss auf die Speichernutzung zur Laufzeit haben können. Wenn die Standard-URP-Shader Ihren Anforderungen nicht entsprechen, können Sie das Aussehen Ihrer Materialien mit Shader Graph anpassen. Erfahren Sie, wie Sie Ihre Shader visuell mit Shader Graph hier erstellen.

Minimieren Sie Überzeichnung und Alpha-Blending
Vermeiden Sie das Zeichnen unnötiger transparenter oder halbtransparenter Bilder. Mobile Plattformen sind stark von der resultierenden Überzeichnung und dem Alpha-Blending betroffen. Überlappen Sie kaum sichtbare Bilder oder Effekte nicht. Sie können die Überzeichnung mit dem RenderDoc Grafik-Debugger überprüfen.
Begrenzen Sie Post-Processing-Effekte
Vollbild Post-Processing Effekte, wie Glühen, können die Leistung dramatisch verlangsamen. Verwenden Sie sie vorsichtig in der künstlerischen Gestaltung Ihres Titels.

Seien Sie vorsichtig mit Renderer.material
Der Zugriff auf Renderer.material in Skripten dupliziert das Material und gibt eine Referenz auf die neue Kopie zurück. Dies bricht jeden bestehenden Batch, der bereits das Material enthält. Wenn Sie auf das Material des gebündelten Objekts zugreifen möchten, verwenden Sie stattdessen Renderer.sharedMaterial.
Optimieren Sie SkinnedMeshRenderer
Das Rendern von skinned Meshes ist teuer. Stellen Sie sicher, dass jedes Objekt, das einen SkinnedMeshRenderer verwendet, es benötigt. Wenn ein GameObject nur manchmal Animation benötigt, verwenden Sie die BakeMesh Funktion, um das skinned Mesh in einer statischen Pose einzufrieren, und wechseln Sie dann zur einfacheren MeshRenderer zur Laufzeit.
Minimieren Sie Reflexionsproben
Eine Reflexionsprobe kann realistische Reflexionen erzeugen, kann aber in Bezug auf Batches sehr kostspielig sein. Verwenden Sie niedrigauflösende Cubemaps, Culling-Masken und Texturkompression, um die Laufzeitleistung zu verbessern.
Dies war der letzte Blogbeitrag in der Serie zur Optimierung der mobilen Leistung. Wenn Sie jedoch Zugriff auf die vollständige Liste von Tipps und Tricks des Teams wünschen, haben wir auch ein 52-seitiges E-Book veröffentlicht, das hier verfügbar ist.

Wenn Sie mehr über die integrierten Supportdienste erfahren möchten und Ihrem Team direkten Zugang zu Ingenieuren, Expertenrat und bewährten Praktiken für Ihre Projekte geben möchten, dann schauen Sie sich die Erfolgpläne von Unity hier an.
Haben Sie nicht gefunden, wonach Sie gesucht haben?
Wir möchten Ihnen helfen, Ihre Unity-Anwendungen so leistungsfähig wie möglich zu gestalten. Wenn es ein Optimierungsthema gibt, über das Sie mehr erfahren möchten, lassen Sie es uns bitte in den Kommentaren wissen.
