Lernen Sie, wie Sie Speicherplatz sparen können, indem Sie die Verwendung von AssetBundles verbessern

JOHN CONSTABLE / UNITY TECHNOLOGIESContributor
Apr 9, 2020|7 Min.
Lernen Sie, wie Sie Speicherplatz sparen können, indem Sie die Verwendung von AssetBundles verbessern
Diese Website wurde aus praktischen Gründen für Sie maschinell übersetzt. Die Richtigkeit und Zuverlässigkeit des übersetzten Inhalts kann von uns nicht gewährleistet werden. Sollten Sie Zweifel an der Richtigkeit des übersetzten Inhalts haben, schauen Sie sich bitte die offizielle englische Version der Website an.

Unabhängig davon, ob Ihre Anwendung Assets von einem Content Delivery Network (CDN) streamt oder sie alle in ein großes Binärformat packt, haben Sie wahrscheinlich schon von AssetBundles gehört. Ein AssetBundle ist eine Datei, die ein oder mehrere serialisierte Assets (Texturen, Meshes, AudioClips, Shader, etc.) enthält und zur Laufzeit geladen werden kann.

AssetBundles können direkt oder über Systeme wie das Unity Addressable Asset System (auch bekannt als Addressables) verwendet werden. Das Addressables-System ist ein Paket, das eine leichter zugängliche und unterstützte Möglichkeit zur Verwaltung von Assets in Ihren Projekten bietet. Es handelt sich um eine Abstraktion über den AssetBundles. Obwohl Addressables die direkte Interaktion von Entwicklern mit AssetBundles minimiert, ist es hilfreich zu verstehen, wie die Verwendung von AssetBundles die Speichernutzung beeinflussen kann. Einen Überblick über das Addressables-System finden Sie in diesem Blog-Beitrag und in dieser Session von der Unite Copenhagen 2019.

Entwickler, die an neuen Projekten arbeiten, sollten die Verwendung von Addressables in Betracht ziehen, anstatt direkt mit AssetBundles zu arbeiten. Wenn Sie an einem Projekt mit einem bereits etablierten AssetBundles-Ansatz arbeiten, helfen Ihnen die Informationen darüber, wie sich AssetBundles auf den Laufzeitspeicher auswirken, dabei, die bestmöglichen Ergebnisse zu erzielen.

Verlust von Speicherplatz an den Speicher-Cache

Wenn Unity ein LZMA-AssetBundle mit der Klasse WWW (die jetzt veraltet ist) oder UnityWebRequestAssetBundle (UWR) herunterlädt, optimiert Unity das Abrufen, erneute Komprimieren und Versionieren von AssetBundles mithilfe von zwei Caches: dem Speicher-Cache und dem Festplatten-Cache.

In den Speicher-Cache geladene AssetBundles verbrauchen viel Speicherplatz. Wenn Sie nicht gerade häufig und schnell auf den Inhalt eines AssetBundles zugreifen wollen, ist der Speicher-Cache die Speicherkosten wahrscheinlich nicht wert. Verwenden Sie stattdessen den Festplatten-Cache.

Wenn Sie ein Versions- oder Hash-Argument für die UnityWebRequestAssetBundle-API angeben, speichert Unity Ihre AssetBundle-Daten im Festplatten-Cache. Wenn Sie diese Argumente nicht angeben, verwendet Unity den Speicher-Cache. Beachten Sie, dass Addressables standardmäßig den Festplatten-Cache verwendet. Dieses Verhalten kann über das Feld UseAssetBundleCache gesteuert werden.

AssetBundle.LoadFromFile() und AssetBundle.LoadFromFileAsync() verwenden immer den Speicher-Cache für LZMA-AssetBundles. Wir empfehlen daher, stattdessen die UnityWebRequestAssetBundle API zu verwenden. Wenn es nicht möglich ist, die UnityWebRequestAssetBundle-API zu verwenden, können Sie AssetBundle.RecompressAssetBundleAsync() verwenden, um ein LZMA-AssetBundle auf der Festplatte neu zu schreiben.

Interne Tests zeigen, dass der Unterschied im Arbeitsspeicher zwischen der Verwendung des Festplatten-Caches und der Verwendung des Speicher-Caches mindestens eine Größenordnung beträgt. Sie müssen abwägen zwischen den Speicherkosten und den zusätzlichen Anforderungen an den Festplattenspeicher und die Asset-Instanzierungszeit für Ihre Anwendung.

Um festzustellen, wie sich der AssetBundle-Speichercache auf die Speichernutzung Ihrer Anwendung auswirkt, verwenden Sie einen nativen Profiler (unser Tool der Wahl ist das Allocations Instrument von Xcode), um Zuweisungen der Klasse ArchiveStorageConverter zu untersuchen. Wenn diese Klasse mehr als 10 MB RAM benötigt, verwenden Sie wahrscheinlich den Speicher-Cache.

Bild
Herausfinden, was Ihre AssetBundles tatsächlich laden

Wenn Sie AssetBundles für große Projekte erstellen, gehen Sie nicht davon aus, dass Unity standardmäßig die Menge der doppelten Informationen in den Bundles minimiert. Um doppelte Daten in den generierten AssetBundles zu identifizieren, können Sie den praktischen AssetBundle Analyzer verwenden, der von einem unserer Kollegen aus der Consulting & Development-Gruppe in Python geschrieben wurde. Das Tool wird über die Befehlszeile verwendet und extrahiert Informationen aus den generierten AssetBundles, die dann in einer SQLite-Datenbank gespeichert werden, die mehrere nützliche Ansichten bietet. Sie können die Datenbank dann mit Tools wie DB Browser for SQLite abfragen. Dieses Tool kann Ihnen helfen, Ineffizienzen in Ihrer Build-Pipeline zu finden und zu beheben, unabhängig davon, ob Sie Bundles manuell oder über Addressables erstellt haben.

Bild

Alternativ können Sie auch das Tool AssetBundle Browser herunterladen und sofort in Ihr Projekt integrieren. Beachten Sie, dass dieses Tool ähnliche Funktionen wie Addressables bietet. Wenn Sie also Addressables verwenden, ist dieses Tool nicht relevant.

Mit dem AssetBundle-Browser können Sie die Konfiguration der AssetBundles in einem bestimmten Unity-Projekt anzeigen und bearbeiten und die Build-Funktionalität nutzen. Außerdem bietet es einige nützliche Funktionen, wie z. B. die Benachrichtigung der Benutzer über doppelte Assets, die aufgrund von Abhängigkeiten (z. B. Texturen) gezogen werden.

Bild
Speicherverlust durch Duplizieren von Assets

Wenn Sie entscheiden, wie Sie Ihre Assets in AssetBundles organisieren, müssen Sie auf die Abhängigkeiten achten. Unabhängig von Ihrer AssetBundle-Topologie unterscheidet Unity zwischen Assets, die sich innerhalb der Anwendungsbinärdatei befinden (in einem oder unter Einbeziehung eines Ressourcenordners) und solchen, die Sie aus AssetBundles laden müssen. Man kann sich diese beiden Arten von Vermögenswerten wie zwei verschiedene Welten vorstellen. Es ist nicht möglich, ein AssetBundle zu erstellen, das einen festen Verweis auf die Instanz eines Assets in der Welt des Ressourcenordners hat. Um diese Assets zu referenzieren, erstellt Unity stattdessen eine Kopie der Assets, die es in der AssetBundle-Welt verwendet.

Bild
Bild

Nehmen Sie zum Beispiel das Logo eines Spiels. Das Logo kann in der Benutzeroberfläche einer Ladeszene angezeigt werden, während das Spiel gestartet wird. Da dieser Ladebildschirm angezeigt werden muss, bevor Remote-Assets auf die Festplatte gestreamt werden, können Sie das Logo-Asset in den Build aufnehmen, damit es sofort verwendet werden kann.

Dasselbe Logo wird auch auf einem Optionsfeld in der Benutzeroberfläche verwendet, in dem der Benutzer seine Sprache, seine Soundpräferenzen und andere Einstellungen auswählen kann. Wenn dieses UI-Panel aus einem AssetBundle geladen wird, erstellt dieses AssetBundle seine eigene Kopie des Logo-Assets.

Wenn sowohl der Ladebildschirm als auch das Optionsfeld gleichzeitig geladen werden, werden beide Kopien des Logo-Assets geladen, was eine Verdoppelung darstellt, die Speicherplatz kostet.

Die Lösung für dieses Problem besteht darin, die feste Verbindung zwischen einem oder beiden Bildschirmen zu unterbrechen. Wenn sich das Logo in einem AssetBundle befindet, muss ein gewisses Streaming stattfinden, bevor Sie einen Verweis auf das Asset erhalten können. Befindet sich das Logo in der Binärdatei (z. B. in einem Ressourcenordner), muss das UI-Panel einen schwachen Verweis auf das Logo-Asset haben und über eine API wie Resources.Load geladen werden.

Bild

Ein guter Mittelweg kann darin bestehen, das AssetBundle, das das Logo-Asset enthält, in das StreamingAssets-Verzeichnis der Anwendung aufzunehmen. Sie laden das Asset immer noch aus dem AssetBundle, aber da Sie das Bundle lokal hosten, entfallen die Zeitkosten für das Herunterladen des Inhalts.

Es ist nicht intuitiv, Strings, Pfade oder GUIDs zu verwenden, um Assets zu referenzieren, aber Sie möchten vielleicht benutzerdefinierte Inspektoren erstellen , die die standardmäßige Drag-and-Drop-Referenzfunktion von Unity für Ihre schwach referenzierten Felder aktivieren. Und vergessen Sie nicht, das Unity-Paket MemoryProfiler zu verwenden, um Assets zu identifizieren, die im Speicher dupliziert sind. Beachten Sie, dass das Addressables-System über einen eigenen Mechanismus zur Prüfung auf Duplikate in Abhängigkeiten verfügt (weitere Informationen finden Sie in der Dokumentation).

Fazit

Auch wenn das Addressables-System eine Abstraktion über AssetBundles darstellt, kann das Wissen, wie die Dinge unter der Haube funktionieren, Ihnen helfen, kostspielige Leistungsprobleme wie die in diesem Artikel beschriebenen zu vermeiden.

Wenn Sie derzeit Addressables nutzen, möchten wir in dieser kurzen Umfrage von Ihnen hören.

Wir planen einen Fahrplan für künftige Einträge in dieser Serie. Gibt es einen Bereich, auf den wir uns Ihrer Meinung nach konzentrieren sollten? Hinterlassen Sie einen Kommentar, um es uns mitzuteilen!