Apprenez à économiser l'utilisation de la mémoire en améliorant la façon dont vous utilisez AssetBundles

Que votre application diffuse des ressources à partir d'un réseau de diffusion de contenu (CDN) ou les regroupe toutes dans un seul gros binaire, vous avez probablement entendu parler d' AssetBundles. Un AssetBundle est un fichier qui contient un ou plusieurs actifs sérialisés (textures, maillages, clips audio, shaders, etc.) et qui peut être chargé au moment de l'exécution.
Les AssetBundles peuvent être utilisés directement ou via des systèmes tels que Unity Addressable Asset System (alias Addressables). Le système Addressables est un package qui fournit un moyen plus accessible et plus pris en charge de gérer les actifs au sein de vos projets. Il s'agit d'une abstraction sur AssetBundles. Bien qu'Addressables minimise les interactions directes des développeurs avec AssetBundles, il est utile de comprendre comment l'utilisation d'AssetBundles peut affecter l'utilisation de la mémoire. Pour un aperçu du système Addressables, veuillez vous référer à cet article de blog et à cette session de Unite Copenhagen 2019.
Les développeurs travaillant sur de nouveaux projets devraient envisager d'utiliser Addressables plutôt que de travailler directement avec AssetBundles. Si vous travaillez sur un projet avec une approche AssetBundles déjà établie, les informations ici sur la façon dont AssetBundles affecte la mémoire d'exécution vous aideront à obtenir les meilleurs résultats possibles.
Lorsque Unity télécharge un AssetBundle LZMA à l'aide de la classe WWW (qui est désormais obsolète) ou d'UnityWebRequestAssetBundle (UWR), Unity optimise la récupération, la recompression et le contrôle de version des AssetBundles à l'aide de deux caches : le cache mémoire et le cache disque.
Les AssetBundles chargés dans le cache mémoire consomment une grande quantité de mémoire. À moins que vous ne souhaitiez spécifiquement accéder fréquemment et rapidement au contenu d’un AssetBundle, le cache mémoire ne vaut probablement pas le coût de la mémoire. Utilisez plutôt le cache disque.
Si vous fournissez une version ou un argument de hachage à l'API UnityWebRequestAssetBundle , Unity stocke vos données AssetBundle dans le cache disque. Si vous ne fournissez pas ces arguments, Unity utilise le cache mémoire. Notez qu'Adressables utilise le cache disque par défaut. Ce comportement peut être contrôlé via le champ UseAssetBundleCache.
AssetBundle.LoadFromFile() et AssetBundle.LoadFromFileAsync() utilisent toujours le cache mémoire pour les AssetBundles LZMA. Nous vous recommandons donc d’utiliser plutôt l’API UnityWebRequestAssetBundle. S'il n'est pas possible d'utiliser l'API UnityWebRequestAssetBundle, vous pouvez utiliser AssetBundle.RecompressAssetBundleAsync() pour réécrire un AssetBundle LZMA sur le disque.
Des tests internes montrent qu'il existe au moins un ordre de grandeur de différence dans la RAM entre l'utilisation du cache disque et l'utilisation du cache mémoire. Vous devez évaluer le compromis entre le coût de la mémoire, les besoins en espace disque supplémentaire et le temps d'instanciation des ressources pour votre application.
Pour déterminer l'effet que le cache mémoire AssetBundle peut avoir sur l'utilisation de la mémoire de votre application, utilisez un profileur natif (notre outil de choix est Allocations Instrument de Xcode) pour examiner les allocations de la classe ArchiveStorageConverter. Si cette classe utilise plus de 10 Mo de RAM, vous utilisez probablement le cache mémoire.

Lorsque vous créez des AssetBundles pour des projets de grande envergure, ne présumez pas qu'Unity minimisera par défaut la quantité d'informations dupliquées entre eux. Pour identifier les instances de données dupliquées dans les AssetBundles générés, vous pouvez utiliser l'outil pratique AssetBundle Analyzer, écrit en Python par l'un de nos collègues du groupe Consulting & Development. Utilisé via la ligne de commande, l'outil extrait des informations des AssetBundles générés, qui sont ensuite stockées dans une base de données SQLite qui propose plusieurs vues utiles. Vous pouvez ensuite interroger la base de données à l'aide d'outils tels que DB Browser pour SQLite. Cet outil peut vous aider à trouver et à résoudre toutes les inefficacités dans votre pipeline de build, que vous ayez créé des bundles manuellement ou via Addressables.

Vous pouvez également consulter l’ outil AssetBundle Browser, que vous pouvez télécharger et intégrer immédiatement à votre projet. Notez que cet outil fournit des fonctionnalités similaires à Addressables, donc si vous utilisez Addressables, cet outil n'est pas pertinent.
L'outil AssetBundle Browser vous permet d'afficher et de modifier la configuration des AssetBundles dans un projet Unity donné et fournit des fonctionnalités de création. Il fournit également des fonctionnalités intéressantes, telles que l'information des utilisateurs sur les ressources dupliquées qui sont extraites en raison de dépendances, telles que les textures.

Lorsque vous décidez comment organiser vos actifs dans des AssetBundles, vous devez faire attention aux dépendances. Quelle que soit la topologie de votre AssetBundle, Unity fait une distinction entre les ressources qui se trouvent dans le binaire de l'application (dans ou impliquant un dossier Ressources) et celles que vous devez charger à partir d'AssetBundles. Vous pouvez considérer ces deux types d’actifs comme vivant dans des mondes différents. Il est impossible de créer un AssetBundle qui possède une référence fixe à l'instance d'un Asset dans le monde du dossier Ressources. Pour référencer ces ressources, Unity crée plutôt une copie des ressources qu'il utilise dans le monde AssetBundle.


Prenons par exemple le logo d’un jeu. Le logo peut être affiché dans l'interface utilisateur d'une scène de chargement pendant le démarrage du jeu. Étant donné que cet écran de chargement doit être affiché avant que les ressources distantes ne soient diffusées sur le disque, vous pouvez inclure la ressource logo dans la build afin qu'elle puisse être utilisée immédiatement.
Ce même logo est également utilisé sur un panneau d'options dans l'interface utilisateur, où les utilisateurs peuvent sélectionner leur langue, leurs préférences sonores et d'autres paramètres. Si ce panneau d'interface utilisateur est chargé à partir d'un AssetBundle, alors cet AssetBundle créera sa propre copie de l'asset du logo.
Si l'écran de chargement et le panneau d'options sont chargés en même temps, les deux copies du logo Asset seront chargées, ce qui constitue une duplication qui coûte de la mémoire.
La solution à ce problème est de rompre le lien physique entre un ou les deux écrans. Si le logo se trouve dans un AssetBundle, une certaine quantité de streaming doit avoir lieu avant que vous puissiez obtenir une référence à l'Asset. Si le logo réside dans le binaire (dans un dossier Ressources, par exemple), le panneau d'interface utilisateur devra avoir une référence faible à l'actif du logo et être chargé via une API telle que Resources.Load.

Les scripts utilisateur devront utiliser la chaîne pour charger l'image au moment de l'exécution et l'affecter au composant approprié. Un juste milieu peut être d'inclure l'AssetBundle contenant le logo Asset dans le répertoire StreamingAssetsde l'application. Vous chargerez toujours l'AssetBundle, mais comme vous hébergez le bundle localement, vous ne paierez pas le coût du temps nécessaire au téléchargement du contenu.
Il n'est pas intuitif d'utiliser des chaînes, des chemins ou des GUID pour référencer des ressources, mais vous souhaiterez peut-être créer des inspecteurs personnalisés qui activent la fonctionnalité de référence par glisser-déposer par défaut d'Unity sur vos champs faiblement référencés. Et n'oubliez pas d'utiliser le package MemoryProfiler d'Unity pour identifier les ressources dupliquées dans la mémoire. Notez que le système Addressables possède son propre mécanisme de vérification des doublons dans les dépendances (pour plus d'informations, consultez la documentation).
Même si le système Addressables fournit une abstraction sur AssetBundles, savoir comment les choses fonctionnent en coulisses peut vous aider à éviter des problèmes de performances coûteux comme ceux décrits dans cet article.
Si vous utilisez actuellement Addressables, nous aimerions connaître votre avis via cette courte enquête.
Nous prévoyons une feuille de route pour les futures entrées de cette série. Y a-t-il un domaine sur lequel vous aimeriez que nous nous concentrions ? Laissez un commentaire pour nous le faire savoir !
