Profilierung und Optimierung eines Unity Web Builds
In diesem Artikel finden Sie Tipps, wie Sie Ihre Unity-Webprojekte optimieren können.
Die früher als "WebGL" bezeichnete Unterstützung für die Unity-Webplattform umfasst wichtige Neuerungen, die die Reibung für mehr Geräte verringern und die neuesten Grafik-APIs nutzen, um selbst für die anspruchsvollsten Webspiele flüssige Bildraten und eine außergewöhnliche Leistung zu gewährleisten.
Dazu gehört die Unterstützung von WebGL, einer JavaScript-API, die 2D- und 3D-Grafiken mit hoher Geschwindigkeit in Browsern darstellt. Google Chrome, Mozilla Firefox, Safari und Microsoft Edge unterstützen alle WebGL 2-Inhalte. WebGL 2 basiert auf OpenGL ES 3.0
Unabhängig von Ihrer Grafik-API sollten Sie darauf achten, dass ein Unity-Webspiel eine geringe Größe hat, damit es sich effizient verteilen und in Websites und soziale Medien einbetten lässt. Sie können ein Web-Build auch für das Prototyping und für Game Jams verwenden, bei denen eine einfache Verteilung wichtig ist, sowie für Tests, selbst wenn Sie auf eine andere Plattform abzielen.
Webspiele können nicht auf lokale Dateien oder Hardware zugreifen und haben im Allgemeinen eine etwas geringere Leistung als nativ kompilierte Spiele.
Hinweis Eine neue API, WebGPU, ist in der Unity 6 Beta (2023.3.0b1 beta) als Early Access verfügbar. WebGPU befindet sich noch in der Entwicklung und wird nicht für den Einsatz in der Produktion empfohlen.
WebGPU wurde mit dem Ziel entwickelt, moderne GPU-Fähigkeiten für das Web nutzbar zu machen und darzustellen. Diese neue Web-API bietet eine moderne Schnittstelle zur Grafikbeschleunigung, die intern über native GPU-APIs wie DirectX12, Vulkan und Metal implementiert wird. Die spezifische native Implementierung hängt von der Plattform des Browsers und den verfügbaren Grafiktreibern ab. Einzelheiten zu den ersten Schritten sowie weitere WebGPU-Demos finden Sie im Grafikforum.
Zur Bereitstellung auf der Unity-Webplattform müssen Sie zunächst das Webmodul zum Unity-Editor hinzufügen, um einen Web-Build zu erstellen. Suchen Sie die Installation im Unity Hub, klicken Sie auf das Symbol Einstellungen und wählen Sie Module hinzufügen.
Blättern Sie in dem neuen Dialogfeld nach unten, um Web Build Support zu finden, wählen Sie es aus und klicken Sie auf Fertig.
Öffnen Sie Ihr Projekt erneut, und wechseln Sie die Zielplattform unter Datei > Build-Einstellungen. Verwenden Sie während der Entwicklung Ihres Spiels die Option Development Build. Es bietet zusätzliche Debugging-Informationen wie Stack Traces, detaillierte Fehlermeldungen und Protokollierungsinformationen, die Sie bei der Fehlersuche und bei Änderungen an Ihrem Spiel unterstützen können. Sie können kleine Änderungen an Ihrem Spielcode, Ihren Assets oder Einstellungen vornehmen und diese Änderungen dann schnell im Browser nachbauen und testen, ohne dass ein vollständiger Build-Prozess erforderlich ist.
Stellen Sie nur sicher, dass Sie die Option "Development Build" in den Build-Einstellungen für Ihren endgültigen veröffentlichten Build deaktivieren.
Wählen Sie Erstellen und Ausführen, um eine Version Ihres Spiels zu erstellen, die in einem Browser zum Testen läuft. Google Chrome ist eine gute Wahl für das Testen von Spielen, da es eine Reihe von Entwickler-Tools bietet.
Sie werden aufgefordert, einen Ort für die Erstellung zu wählen. Die Dateien des Builds enthalten eine index.html-Datei, die ein HTML5-Canvas-Element zum Document Object Model (DOM) hinzufügt. DOM ist die Datendarstellung der Objekte, die die Struktur und den Inhalt eines Dokuments im Web bilden. Das Spiel wird auf dieser Leinwand gerendert. Die Build-Dateien enthalten auch einen Ordner TemplateData und einen Ordner Build. Der Ordner TemplateData enthält die auf der Seite verwendeten HTML-Assets, z. B. das Favicon in der Adressleiste des Browsers und die im HTML-Markup der Seite verwendeten Bilder.
Sie können auch automatisierte Builds einrichten, wobei die Unity Build Automation eine Option dafür ist.
Sie können die integrierte Render-Pipeline oder die Universal Render Pipeline (URP) für ein Webspiel verwenden. Wir empfehlen jedoch URP, da es eine effiziente Anpassung und Skalierung von Inhalten für mehrere Hardware-Geräte ermöglicht.
Holen Sie sich eine ausführliche Anleitung, wie Sie Ihre Projekte von der Built-in Render Pipeline auf URP umstellen können, mit dem E-Book Einführung in die Universal Render Pipeline für fortgeschrittene Unity-Entwickler.
Wenn Sie eine Konsole anvisieren, haben Sie genaue Spezifikationen für Speicher, CPU- und GPU-Nutzung. Das Web ist eine ganz andere Angelegenheit. Um Ihr Spiel einem möglichst breiten Publikum zugänglich zu machen, müssen Sie sicherstellen, dass es auch in einer Umgebung mit begrenztem Speicherplatz gut funktioniert.
Hier sind einige Tipps aus dem E-Book, wie Sie Ihr Spiel auch auf leistungsschwacher Hardware zum Laufen bringen können Optimieren Sie die Leistung Ihres mobilen Spiels.
1. Optimieren Sie Ihre Spiel-Assets
Optimieren Sie Assets wie Texturen und Modelle für das Web, verwenden Sie z. B. komprimierte Texturen und reduzieren Sie die Anzahl der Polygone in Ihren Modellen, wo dies möglich ist. Auch wenn es keine festen Regeln gibt, sollten Sie sich in Ihrem Team auf einige allgemeine Richtlinien einigen, um eine einheitliche Leistung zu gewährleisten.
2. Objektpooling verwenden
Das Pooling von Objekten ist eine Technik, mit der Sie die Leistung verbessern können, indem Sie Objekte wiederverwenden, anstatt neue Objekte zu erstellen und zu zerstören. Dies kann für Spiele mit viel Spawning und Despawning nützlich sein. Andere Programmiermuster wie das Schwungrad können ebenfalls hilfreich sein. Siehe das E-Book Verbessern Sie Ihren Code mit Programmiermustern für Spielefür fortgeschrittene Tipps zur Implementierung von Entwurfsmustern in Unity-Projekten.
3. Verwenden Sie die Universal Render Pipeline und den SRP Batcher
Verbessern Sie die Leistung mit dem SRP Batcher-System von Unity, das das CPU-Rendering je nach Szene beschleunigt. Dabei werden Zeichenaufrufe auf der Grundlage gemeinsamer Materialeigenschaften wie Shader und Texturen gruppiert, wodurch die Anzahl der beim Rendern erforderlichen Zustandsänderungen verringert wird.
4. Okklusionsausblendung verwenden
Das Occlusion Culling System in Unity kann helfen, die Leistung zu verbessern, indem es nur die Objekte rendert, die für den Spieler sichtbar sind. Occlusion Culling funktioniert am besten in Szenen, in denen kleine, klar definierte Bereiche durch solide GameObjects voneinander getrennt sind, wie z.B. Räume, die durch Korridore verbunden sind.
5. Verwenden Sie das integrierte LOD-System (Level of Detail)
Das in Unity integrierte LOD-System verbessert die Leistung, indem es die Komplexität von Objekten, die weiter vom Spieler entfernt sind, reduziert. Wenn der Abstand zwischen der Kamera und einem Objekt zunimmt, tauscht das LOD-System automatisch die Version des Objekts mit hohem Detailgrad gegen eine Version mit niedrigerem Detailgrad aus, um den Renderingaufwand zu verringern und gleichzeitig ein kohärentes Erscheinungsbild zu erhalten.
6. Backen Sie Ihre Beleuchtung, wenn möglich
Verbessern Sie die Leistung, indem Sie Beleuchtungsinformationen für Ihre Szenen mit Lightmaps und Light Probes vorberechnen.
7. Unnötige Erstellung oder Manipulation von Zeichenfolgen reduzieren
In C# sind Strings Referenztypen, keine Werttypen. Vermeiden Sie das Parsen von String-basierten Datendateien wie JSON und XML; speichern Sie stattdessen Daten in ScriptableObjects oder Formaten wie MessagePack oder Protobuf. Sie können auch Binärformate für Fälle wie das Speichern von dauerhaften Spieldaten (Spielstände) in Betracht ziehen. Verwenden Sie die StringBuilder-Klasse, wenn Sie Strings zur Laufzeit erstellen müssen.
8. Das Addressable Asset System ausprobieren
Das Addressable Asset System vereinfacht die Verwaltung Ihrer Inhalte durch das Laden von AssetBundles nach "Adresse" oder Alias. Dieses vereinheitlichte System lädt asynchron entweder von einem lokalen Pfad oder einem entfernten Content Delivery Network (CDN).
9. Begrenzung der Nachbearbeitungseffekte
Post-Processing-Effekte im Vollbildmodus können die Leistung beeinträchtigen, daher sollten Sie sie in Ihrem Spiel nur sparsam einsetzen.
Wenn Sie einen Unity-Web-Build erstellen, verwendet Unity eine Vorlage, um die Webseite zur Anzeige Ihres Spiels zu generieren.
Die Standardvorlagen sind:
- Standard: Eine weiße Seite mit einem Ladebalken auf einer grauen Leinwand
- Minimal: Die minimale Boilerplate, die zum Betrieb Ihres Spiels benötigt wird
- Progressive Web-App (PWA): Dazu gehören eine Webmanifestdatei und ein Service Worker. In einem geeigneten Desktop-Browser wird in der Adressleiste eine Installationsschaltfläche angezeigt, mit der das Spiel zu den startbaren Anwendungen des Spielers hinzugefügt werden kann.
Der einfachste Weg, eine eigene HTML-Seite zu erstellen, ist, mit einer der drei Vorlagen zu beginnen, die Sie über <UnityInstallation>/PlaybackEngines/ WebGLSupport/ BuildTools/ WebGLTemplates/ finden. Auf dem Mac finden Sie den Unity-Installationsordner im Ordner "Programme".
Kopieren Sie eine Vorlage, legen Sie sie in Ihrem eigenen Ordner Project/Assets/WebGLTemplates ab und benennen Sie sie um, damit Sie sie später identifizieren können. Sie können sie nun an den Spielinhalt, den Einsatzort und die Zielplattform anpassen.
Vorlagen im Ordner WebGLTemplates Ihres Projekts werden im Bereich Bearbeiten > Projekteinstellungen... > Player > Auflösung und Darstellung angezeigt. Der Name der Vorlage ist derselbe wie ihr Ordner. Um diese Option mit einem Vorschaubild zu versehen, fügen Sie ein 128 x 128 Pixel großes Bild in den Vorlagenordner ein und nennen Sie es thumbnail.png.
Während des Build-Prozesses verarbeitet Unity die Vorlagendateien und wertet alle Makros und bedingten Direktiven aus, die in diesen Dateien enthalten sind. Es findet und ersetzt alle Makro-Deklarationen mit den Werten, die der Editor liefert, und verarbeitet automatisch alle .html-, .php-, .css-, .js und .json-Dateien im Vorlagenordner vor.
Schauen Sie sich zum Beispiel diese Codezeile an:
<canvas id="unity-canvas" width={{{ WIDTH }}} height={{{ HEIGHT }}} tabindex="-1"></canvas>
Wenn im Bedienfeld Auflösung und Darstellung die Standard-Leinwandbreiteauf 960 und die Standard-Leinwandhöhe auf 600 eingestellt ist, sieht der Code nach der Vorverarbeitung wie folgt aus:
<canvas id="unity-canvas" width="960" height="600" tabindex="-1"></canvas>.
Dreifach geschweifte Klammern zeigen dem Compiler an, dass er den Wert der angegebenen Variable suchen soll.
In den Standardvorlagen finden Sie auch Beispiele für bedingte Direktiven mit #if, #else und #endif:
#if EXPRESSION
//Wenn EXPRESSION einen wahrheitsgemäßen Wert ergibt
#else
//Wenn EXPRESSION nicht als wahrheitsgemäßer Wert ausgewertet werden kann
#endif
Wenn Sie eine benutzerdefinierte Vorlage verwenden möchten, bietet der Unity Asset Store eine Reihe von Optionen.
Wenn Sie Ihr Spiel auf einer Plattform für browserbasierte Spiele bereitstellen, müssen Sie die index.html-Seite an eine Spezifikation anpassen. In der Dokumentation einiger beliebterer Plattformen für Webspiele finden Sie Hinweise zu dieser Vorgehensweise:
Sie werden oft wollen, dass Ihr Spiel die Größe eines Browserfensters ändert, um ein responsives Design zu ermöglichen, was eine Anpassung des Ladecodes erfordert. Um dies zu erreichen, können Sie in JavaScript ein "Promise" verwenden, das einen Vorgang darstellt, der noch nicht abgeschlossen ist, aber in der Zukunft erwartet wird, dass er abgeschlossen wird.
In der index.html-Seite für jede Vorlage (siehe das Codebeispiel unten) finden Sie script.onload. Das script.onload ist ein Ereignis, das ausgelöst wird, wenn das Skript der Unity-Engine fertig geladen ist. Kurz bevor dies geschieht, gibt es zwei globale Variablen: myGameInstance, die den Verweis auf die Unity-Instanz enthält, und myGameLoaded, die anzeigt, ob das Spiel fertig geladen ist oder nicht, und standardmäßig false ist. Sie werden als var deklariert, so dass sie einen globalen Geltungsbereich haben und überall im Skript aufgerufen werden können.
Die Funktion createUnityInstance() wird aufgerufen, um eine neue Instanz des Unity-Spiels zu erstellen. Diese Funktion gibt ein Promise zurück, das aufgelöst wird, wenn das Spiel vollständig geladen und bereit zum Rendern ist (der then-Block des createUnityInstance Promise).
Innerhalb von then() wird myGameInstance die Unity-Instanz zugewiesen, und myGameLoaded wird auf true gesetzt, was anzeigt, dass das Spiel jetzt bereit ist. Die Funktion resizePage() wird dann aufgerufen, um die Größe des Spiels anfangs festzulegen, und ein Ereignis-Listener wird zum Größenänderungsereignis des Fensters hinzugefügt, damit die Größe des Spiels bei jeder Größenänderung des Fensters aktualisiert werden kann. Siehe nachstehendes Codeschnipsel.
Am Ende des Skripts befindet sich die Funktion resizePage, wie im folgenden Codeschnipsel gezeigt, mit der die Größe des Spiels an die Größe des Fensters angepasst wird. Wenn das Spiel geladen ist, werden die Stilwerte für die Leinwand, auf der das Spiel angezeigt wird, so eingestellt, dass sie der Fenstergröße entspricht und das Fenster ausfüllt:
Funktion resizePage(){
if (myGameInstance !== undefined && myGameLoaded === true)
{
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
}
}
Viele Spiele, die auf einen Browser abzielen, müssen mit JavaScript-Code interagieren, damit Sie Webdienste zur Unterstützung von Benutzeranmeldungen, Highscore-Tabellen usw. oder zur Interaktion mit dem Browser-DOM aufrufen können. Jedes JavaScript, das Sie direkt hinzufügen, damit es von einem C#-Skript aufgerufen werden kann, muss die Erweiterung .jslib haben und im Ordner Assets/Plugins abgelegt werden. Sie sollte in die mergeInto-Methode eingeschlossen werden. Dazu sind zwei Parameter erforderlich: LibraryManager.library und dann ein JavaScript-Objekt, das eine oder mehrere Funktionen enthält. Die Funktionen sind Standard-JavaScript. GetExchangeRates zeigt, wie man einen einfachen JSON-liefernden Webdienst verwendet.
Wenn du einen Build erstellst, werden diese Funktionen der Datei Build/<Name deines Spiels>.framework.js hinzugefügt. Sie können diese Funktionen von einem C#-Skript aus aufrufen, indem Sie die Funktion als DllImport deklarieren, wie in diesem Codebeispiel gezeigt:
public class SphereController : MonoBehaviour
{
[DllImport("__Internal")]
private static extern void GetExchangeRates();
private void Start()
{
GetExchangeRates();
}
}
Weitere Informationen
Zusätzlich zu C#, das eine JavaScript-Funktion aufruft, kann JavaScript eine C#-Methode aufrufen. Der betreffende Mechanismus verwendet ein Nachrichtenprotokoll:
myGameInstance.SendMessage(‘MyGameObject’, ‘MyFunction’)
myGameInstance.SendMessage(‘MyGameObject’, ‘MyFunction’, 5)
myGameInstance.SendMessage(‘MyGameObject’, ‘MyFunction’, ‘A string’)
Um SendMessage zu verwenden, benötigen Sie einen Verweis auf die Spielinstanz im Geltungsbereich. Die übliche Technik besteht darin, index.html zu bearbeiten, indem man eine globale Variable hinzufügt und diese im then-Block des skript.onload Promise zuweist, wie zuvor gesehen. Diese einfache Funktion wird als Teil einer MonoBehaviour-Komponente hinzugefügt, die an ein GameObject namens Sphere angehängt ist.
public void SetHeight( float height )
{
Vector3 pos = transform.position;
pos.y = Höhe;
transform.position = pos;
}
Sie können die Konsole von Chrome mit F12 öffnen und direkt eingeben:
myGameInstance.SendMessage('Sphere', 'SetHeight', 3)
Drücken Sie die Eingabetaste, um die Funktion Sphäre bewegen aufzurufen. Die Bewegung wird nur dann im Rendering widergespiegelt, wenn Sie " Im Hintergrund ausführen" oder "Application.runInBackground" auf true gesetzt haben. Das liegt daran, dass das Rendern standardmäßig nur erfolgt, wenn das Canvas-Fenster den Fokus hat.
Verwenden Sie Debug.Log beim Debuggen für Browser-Plattformen. Alle Meldungen werden an die Konsole des Browsers gesendet. In Chrome finden Sie dies, indem Sie F12 drücken und zur Registerkarte Konsole wechseln. Die Klasse Debug bietet jedoch mehr Möglichkeiten. Mit Debug.LogError liefert die Konsole einen Stack-Trace, der hilfreich sein kann.
Weitere Informationen
Wir empfehlen Ihnen, während der Entwicklung die Option "Development Build" zu verwenden, aber diese Option zu deaktivieren, wenn Sie Ihr Spiel auf einer Live-Site bereitstellen. Bei einem Release-Build haben Sie die Möglichkeit der Komprimierung. Möglicherweise müssen Sie die Einstellungen auf Ihrem Server anpassen, wenn Sie die Komprimierung verwenden; Tipps dazu finden Sie im Handbuch.
Es ist wichtig, Ihr Projekt während des gesamten Entwicklungszyklus zu profilieren, damit Sie Leistungsprobleme rechtzeitig erkennen. Der Unity Profiler ist ein gutes Werkzeug, um Leistungsengpässe in Ihrem Spiel zu identifizieren und zu beheben. Es verfolgt die CPU- und Speichernutzung und hilft Ihnen, Bereiche Ihres Spiels zu identifizieren, die optimiert werden müssen. Daneben können Sie auch den Profile Analyzer, den Memory Profiler und das Web Diagnostics Overlay verwenden.
Das E-Book herunterladen Ultimative Anleitung zum Profiling von Unity-Spielen um mehr über die Profilerstellung in Unity zu erfahren.
Im Folgenden finden Sie einige Tipps für den Einstieg in das Profiling eines Unity Web Builds.
Aktivieren Sie den Unity-Profiler
Gehen Sie im Editor zu Datei > Build-Einstellungen und wählen Sie Development Build und Autoconnect Profiler , um den Profiler mit einem Web-Build zu verwenden.
Wählen Sie das Modul CPU-Auslastung
Verwenden Sie dieses Modul, um die Leistung Ihres Codes zu analysieren und Bereiche zu identifizieren, die Leistungsprobleme verursachen. Analysieren Sie Elemente wie Funktionsaufrufe, Skriptausführung und Garbage Collection.
Wählen Sie das Modul Memory Profiler
Unity Web Builds haben im Vergleich zu anderen Plattformen nur begrenzte Speicherressourcen. Verwenden Sie dieses Modul, um die Speichernutzung Ihrer Anwendung zu analysieren und Bereiche mit Optimierungsbedarf zu ermitteln.
Verwenden Sie das Chrome DevTools Performance-Panel
Chrome DevTools enthält ein Performance-Panel, das Ihnen hilft, Engpässe in Ihrem Spiel aufzuspüren. Es bietet unter anderem ein Sources-Panel zum Hinzufügen von Haltepunkten in JavaScript-Dateien und ein Console-Panel zum Anzeigen von Debug-Meldungen und zur Eingabe von JavaScript-Code.
Leistung auf verschiedenen Geräten messen
Auf diese Weise können Sie Leistungsprobleme erkennen, die möglicherweise auf ein bestimmtes Gerät oder einen bestimmten Browser zurückzuführen sind, und Ihr Spiel entsprechend optimieren.
Reduzieren Sie die Anzahl der Auslosungsaufrufe
Draw-Aufrufe sind einer der größten Leistungsengpässe für Unity-Web-Builds. Verwenden Sie den Unity Profiler, um Bereiche mit einer hohen Anzahl von Zeichenaufrufen zu identifizieren und versuchen Sie, diese zu reduzieren.
Analysieren Sie die Leistung auf Low-End-Geräten
Testen Sie auf Low-End-Geräten, um sicherzustellen, dass Ihre Anwendung für eine breite Palette von Hardware optimiert ist.
Aktivieren Sie "Im Hintergrund laufen" während der Profilerstellung
Wenn " Im Hintergrund ausführen" in den WebGL-Player-Einstellungen aktiviert ist oder wenn Sie " Application.runInBackground" aktivieren, wird Ihr Inhalt weiter ausgeführt, wenn die Leinwand oder das Browserfenster den Fokus verliert.
Unity-Web-Builds sind eine großartige Möglichkeit, Ihr Spiel einem breiten Publikum zugänglich zu machen. Während der Entwicklung sollten Sie darauf achten, Geometrie und Texturen auf eine bescheidene Größe zu beschränken, Zeichnungsaufrufe zu reduzieren und Profile zu erstellen und auf einer breiten Palette von Geräten zu testen. Und schließlich sollten Sie URP verwenden, um eine solide Leistung über ein breites Spektrum von Hardware zu gewährleisten.
Weitere Informationen
Tipps und Tricks zur Verwendung des WebGL-Moduls von Unity
Früher Zugang zum neuen WebGPU-Backend in Unity 2023.3
Alle fortgeschrittenen E-Books und Artikel von Unity finden Sie im Unity Best Practices Hub.