Questions et réponses élargies : Optimisation de la mémoire et de la taille des fichiers avec Addressables

PATRICK DEVARNEY / UNITY TECHNOLOGIESContributor
Apr 28, 2023|17 Min
Questions et réponses élargies : Optimisation de la mémoire et de la taille des fichiers avec Addressables
Cette page a été traduite automatiquement pour faciliter votre expérience. Nous ne pouvons pas garantir l'exactitude ou la fiabilité du contenu traduit. Si vous avez des doutes quant à la qualité de cette traduction, reportez-vous à la version anglaise de la page web.

En février, dans le cadre de mon rôle de consultant principal en développement de logiciels pour Unity Accelerate Solutions, j'ai animé un webinaire technique sur le système d'actifs adressables. Au cours de la session en direct, j'ai présenté différents outils de profilage que vous pouvez utiliser pour optimiser la mémoire d'exécution et la taille de construction d'un projet. Le webinaire s'est terminé par une séance de questions-réponses, et notre équipe a reçu plus de questions que nous n'avons eu le temps d'y répondre.

Ce qui suit est un prolongement de cette dernière séance de questions-réponses, afin que nous puissions répondre à un plus grand nombre de vos questions.

Q : Le système Addressables est-il nécessaire pour les jeux légers - tels que les jeux occasionnels, les jeux d'arcade ou les jeux de réflexion - si je n'ai pas de problèmes de mémoire ?
A : Peut-être pas, mais il est bon de garder à l'esprit que le système Addressables n'améliore pas seulement les performances de la mémoire. La possibilité de choisir le moment où vous chargez le contenu peut améliorer les temps de chargement. La création de contenu dans Addressables vous permet d'avoir des créations itératives qui ne prennent pas autant de temps. Par exemple, si vous apportez une petite modification à un script, vous n'aurez peut-être pas à reconstruire tous vos paquets.

Q : Les ressources chargées sont-elles libérées lorsque la scène change ?
A : Potentiellement. Les ressources chargées à partir d'objets adressables qui sont prêtes à être libérées parce qu'elles ont un nombre de références égal à zéro peuvent être déchargées de la mémoire au cours d'une transition de scène. Lors de la transition de scènes de manière non additive, appelez Resources.UnloadUnusedAssets(). Cette opération est coûteuse pour l'unité centrale, mais elle permet de décharger partiellement les AssetBundles.

Q : La mise en commun d'objets et les produits adressables fonctionnent-ils bien ensemble ?
A : Oui. Vous pouvez charger votre objet une fois à partir d'Addressables et en instancier plusieurs copies pour créer votre pool. Lorsque vous avez terminé avec le pool, détruisez tous les objets et libérez le AsyncOperationHandle qui a été utilisé pour charger l'actif.

Q : Les groupes et les paquets sont-ils chargés en mémoire en une seule fois ?
A : Les groupes adressables sont un concept propre à l'éditeur. Au moment de l'exécution, vous n'avez affaire qu'à des paquets. Les paquets ne sont chargés dans la mémoire que lorsqu'ils sont nécessaires et seul le contenu souhaité est chargé.

Exemple : Vous disposez d'une liasse contenant 10 caractères. Vous demandez à Addressables de charger trois caractères. Les métadonnées de la liasse et les trois caractères seront chargés.

Q : Si je veux libérer un actif, dois-je conserver l'AsyncOperationHandle ou l'AssetReference ?
A : Nous vous recommandons de conserver la poignée et de l'utiliser, car vous êtes responsable de la publication du contenu lorsque vous avez fini de l'utiliser.

Par exemple, les membres de notre équipe choisissent souvent la voie de la poignée afin d'éviter d'appeler Instantiate/Release directement sur l'AssetReference.

Q : Quels sont les inconvénients d'un grand nombre de petites liasses ?
A : Cette documentation énumère plusieurs inconvénients liés à un trop grand nombre de liasses.

Q : Lorsqu'un actif d'une offre groupée est nécessaire, quels sont les frais généraux des autres actifs de la même offre groupée ? S'il s'agit d'une offre groupée à distance, elle doit être téléchargée, mais n'y a-t-il vraiment pas de surcharge de mémoire due à des actifs inutilisés dans l'offre groupée ?
A : Correct, une offre groupée à distance doit être entièrement téléchargée avant que vous puissiez l'utiliser.

Les ressources non chargées d'un ensemble de ressources chargées ont une incidence minimale sur l'exécution. Chaque fois que vous chargez des ressources à partir d'un ensemble, vous devez charger les métadonnées de cet ensemble. Une partie de ces métadonnées comprend une table des matières qui répertorie toutes les ressources de l'ensemble. Un plus grand nombre d'actifs dans un paquet équivaut à un plus grand nombre de métadonnées.

Vous pouvez visualiser cette surcharge de mémoire en prenant une capture avec le Unity Memory Profiler. Dans l'onglet "All Of Memory", il y a une liste de tous les objets "SerializedFile" en mémoire, un pour chaque bundle. Ces objets sont les métadonnées de vos paquets.

Pour en savoir plus sur ces métadonnées, consultez notre documentation.

Q : Lorsque je travaille dans un monde ouvert, quelles stratégies de regroupement puis-je utiliser pour décharger des actifs individuels sans décharger à moitié un paquet et dépendre de Resources.UnloadUnusedAssets() pour le nettoyer, sans avoir la charge de travail d'avoir chaque actif dans son propre paquet ?
A : L'essentiel est de garder à l'esprit que le contenu doit être regroupé si vous comptez le décharger en même temps. Si votre monde de jeu a un contenu "statique", comme les arbres et les rochers d'un certain biome qui ne seront pas déplacés par le joueur, ce contenu doit être regroupé. Tout contenu "dynamique", comme les objets que le joueur peut ramasser, doit être regroupé séparément.

Cet article de blog et le repo GitHub lié couvrent le fractionnement des paquets pour un jeu à monde ouvert. Il permet également de dédupliquer les paquets afin de réduire l'encombrement de la mémoire de chaque paquet. Les étapes 4 et 5 sont particulièrement pertinentes pour les mondes ouverts.

Q : Quand dois-je laisser l'option "AssetBundle CRC" activée ?
A : Il est recommandé d'activer cette fonction, en excluant les AssetBundles mis en cache pour les groupes distants, et de la désactiver pour les groupes locaux. Le contrôle vise uniquement à s'assurer que les données n'ont pas été corrompues lors du téléchargement. Il n'y a pratiquement aucune raison de vérifier les AssetBundles locaux.

Q : Quand n'est-il pas utile d'utiliser les adresses en raison des problèmes de performances du processeur lors du chargement et du déchargement des ressources ?
A : Le système Addressables a un impact positif sur les performances de chargement de l'unité centrale, car il n'est pas nécessaire de charger tout le contenu en amont.

Si vous n'utilisez pas les adressables lors du chargement d'une scène, vous devrez charger tout le contenu et toutes les références. Si vous déplacez le contenu vers Adressables, vous pouvez choisir le moment du chargement du contenu.

Par exemple, supposons que vous ayez un gestionnaire d'inventaire dans une scène qui fait référence à 1 000 articles d'inventaire. Si vous n'utilisez pas les adressables, vous devrez charger chaque mesh, texture, clip audio, etc. pour tous ces éléments d'inventaire. Si vous attendez pour charger ce contenu, le chargement de la scène sera plus rapide.

Q : Toutes les dépendances d'un bien adressable doivent-elles également être adressables, ou cela n'est-il nécessaire que si elles sont partagées ?
A : Les dépendances n'ont pas besoin d'être marquées comme adressables. Les dépendances seront intégrées à Addressables au cours du processus de construction si nécessaire.

Par exemple, si vous rendez un joueur préfabriqué adressable, vous n'avez pas besoin de marquer manuellement le mesh, les textures ou l'audio du joueur comme adressables également. Lorsque le pack est construit, toutes les dépendances qui n'existent pas encore dans Addressables seront automatiquement incluses dans le pack de préfabrication du lecteur.

Q : Si j'ai oublié de libérer un bien et que je change de scène, qu'advient-il de ce bien ?
A : Le fait de changer de scène n'entraîne pas nécessairement une mauvaise interaction avec les poignées. Mais si vous chargez un bien et que vous oubliez de relâcher sa poignée, le bien persistera dans la mémoire.

Addressables dispose d'un système de comptage de référence interne. Les poignées sont la façon dont nous interagissons avec ce système. Le chargement d'un poste incrémente le nombre de références et sa libération le décrémente.

Les créateurs sont responsables de la mise à jour de ce nombre de références. Le bien sera en mémoire tant que le nombre de références sera supérieur à un.

Q : En ce qui concerne l'exemple du webinaire, supposons que je crée un jeu à monde ouvert. Le boss est présent quelque part dans le monde ouvert. Lorsque le joueur se dirige vers le boss, comment puis-je utiliser les adresses ici ? Dois-je envoyer la commande de chargement de l'épée de manière asynchrone, via un déclencheur, à une certaine distance de l'ennemi, ou autre chose ?
A : Le choix du moment de chargement et de déchargement du contenu peut s'avérer délicat. Il faut s'assurer que le boss est prêt lorsque le joueur a besoin de le voir, mais il ne faut pas le charger trop tôt lorsque le joueur peut encore se retourner et l'éviter.

L'avantage est que vous pouvez itérer sur le moment de charger et de décharger le contenu - vous n'êtes pas obligé de l'optimiser parfaitement du premier coup.

Pour commencer, nous suggérons de charger tout le contenu d'une "zone" particulière lorsque le joueur s'en approche (par exemple, le joueur s'approche de l'entrée d'un donjon, ce qui entraîne le chargement de tout ce qui se trouve à l'intérieur du donjon). Si cela entraîne une pression inutile sur la mémoire, vous pouvez ajouter un chargement et un déchargement plus précis.

Si l'épée ne se charge pas assez rapidement, envisagez de déplacer le déclencheur de chargement pour qu'il commence plus tôt, d'améliorer le temps de chargement des ressources de l'épée en utilisant le module CPU d'Unity Profiler pour voir ce qui est en train d'être chargé, ou d'utiliser les adressables de manière synchrone pour s'assurer que le chargement est terminé.

Cette documentation contient plus de détails et un extrait de code pour les adressables synchrones.

Q : Si je charge un objet adressable au début d'une scène, dois-je avoir un écran de chargement pour cet objet ?
A : Le chargement à partir d'adresses est généralement effectué de manière asynchrone, comme avec Addressables.LoadAssetAsync().

Il se peut que vous ne souhaitiez pas charger certains contenus avant de quitter l'écran de chargement. Vous pouvez collecter ces AsyncOperationHandles et attendre que les AsyncOperationHandles nécessaires soient terminés avant de partir.

Q : Quelle est l'empreinte mémoire des métadonnées adressables au moment de l'exécution (avant le chargement des données) ?
A : Lors de l'initialisation d'Addressables, le fichier de catalogue est chargé afin qu'Addressables sache comment associer les étiquettes et les adresses aux actifs sur le disque ou dans des emplacements distants. Un catalogue plus important se traduit par une surcharge de mémoire plus importante au moment de l'exécution.

La taille du catalogue peut être réduite en supprimant les données inutiles, par exemple en n'incluant pas les étiquettes ou les GUID dans les groupes qui n'en ont pas besoin, ou en réduisant la taille des données existantes. Par exemple, en définissant le mode de désignation interne des ressources d'un groupe sur GUID au lieu de nom de fichier ou de chemin d'accès complet (qui peut être plus long). Vous pouvez visualiser la taille de la mémoire d'exécution du catalogue dans Unity Memory Profiler.

Q : Que fait l'éditeur Unity pendant le temps qu'il consacre à la construction des adresses ?
A : Un rapport de construction est produit dans le dossier /Library. Ce journal montre chaque étape du processus de construction. Pour ajouter des détails supplémentaires au journal, suivez ce chemin pour sélectionner "Use Detailed Build Log" : Activation de Edit > Preferences > Scriptable Build Pipeline > Use Detailed Build Log.

Consultez les visuels et la documentation sur la façon de visualiser le journal.

Q : Resources.Load() présente-t-il également un problème de duplication ?
A : Oui. Il peut être utile de considérer le contenu "adressable" et le contenu "ressources" comme des "mondes" différents. Si vous avez une texture dans /Ressources, une copie de cette texture est incluse dans le fichier Ressources. Si des paquets dans Addressables dépendent de cette texture, chaque paquet comprend une copie implicite de celle-ci. Vous vous retrouvez avec plusieurs copies de la texture sur le disque et potentiellement plusieurs copies en mémoire.

Pour éviter cette duplication, déplacez la texture hors de /Resources et ajoutez-la à un groupe d'objets adressables.

Q : Les problèmes de taille sur le disque qui sont résolus en supprimant les paquets dupliqués sont-ils similaires lorsque vous n'utilisez pas Addressables ?
A : Oui. Dans le webinaire et les diapositives, nous montrons comment la déduplication des deux scènes de course d'eau a permis de réduire considérablement la taille de la construction.

Q : Comment éviter les doublons de variantes de shaders ?
A : Les shaders peuvent être dédupliqués de la même manière que n'importe quelle autre ressource - en les déclarant explicitement dans un groupe.

Si une ressource est explicitement déclarée dans un groupe d'adresses qui sera intégré à votre construction, cette ressource ne sera pas dupliquée dans plusieurs paquets.

Pour les shaders en particulier, il est courant que les projets utilisent un groupe "Shared shaders" pour contenir les shaders dont vous pensez avoir besoin en mémoire pendant toute la durée de vie de votre application, et qui sont partagés par de nombreux actifs.

Q : Deux scènes Unity partageant la même préfabrication dupliquent-elles la taille de la construction ?
A : Cela dépend si le préfabriqué dont dépendent les scènes a été explicitement inclus dans Addressables, et si les scènes se trouvent dans le même paquet ou dans des paquets différents.

L'explication visuelle de la duplication se trouve dans les diapositives du webinaire et dans cet article de blog à l'étape 4.

L'essentiel est de se rappeler que tout le contenu d'une liasse doit pouvoir accéder à toutes ses dépendances. Si vous placez une scène dans un bundle, toutes ses dépendances doivent être soit :

  • Incluse explicitement quelque part dans les données adressables
  • Implicitement inclus dans la même offre

Q : Est-il possible de comparer les doublons dans des groupes donnés afin d'éviter que tous les actifs du jeu soient regroupés dans un groupe isolé ?
A : Oui. Vous pouvez exécuter la règle de déduplication intégrée, puis trier les actifs dans la fenêtre Groupes d'adresses en les regroupant mieux.

Ou bien, une approche plus évolutive consiste à écrire vos propres règles d'analyse d'adressables, qui apparaîtront dans la fenêtre d'analyse. Les règles intégrées sont fournies en C# dans le paquet Addressables et peuvent servir de référence.

Par exemple, vous pouvez rechercher tous les doublons dans tous vos groupes qui commencent par "Caractère-". Les doublons implicites peuvent être placés dans un groupe de "personnages partagés".

Q : Allez-vous couvrir les constructions à distance et les chemins d'accès locaux ?
A : Nous n'avons pas abordé les chemins d'accès locaux et distants, qui sont appelés "profils adressables" dans le webinaire. Cependant, nous décrivons dans cette documentation ce que sont les profils d'adressage et comment les utiliser.

Q : Comment Addressables fonctionne-t-il avec Cloud Content Delivery (CCD) ?
A : L'intégration du CCD est abordée dans cette documentation.

Q : Pouvez-vous nous donner des indications sur les meilleures pratiques pour mettre en œuvre des variations d'adressage à basse et haute résolution ?
A : Vous trouverez un exemple dans l'Addressables Sample sur GitHub.

Q : Que se passe-t-il si le contenu de la liasse est crypté ? L'outil UnityDataTool décrypte-t-il également le contenu ?
A : Non. Les données devront être décryptées avant que UnityDataTool puisse analyser le contenu.

Q : Est-il possible de construire des bundles à partir d'un projet Unity et de charger les bundles au moment de l'exécution à partir d'une application construite à partir d'un autre projet ?
A : Oui. Ceci est couvert par l'utilisation de plusieurs catalogues en même temps.

Q : Y a-t-il des inconvénients à utiliser InstantiateAsync, ou des situations où il est préférable d'utiliser LoadAsync + Instantiate manuel ?
A : Il est recommandé d'utiliser Addressables.LoadAssetAsync() et d'appeler Object.Instantiate(). Addressables.InstantiateAsync() a un coût de performance plus important.

Q : J'ai beaucoup de ScriptableObjects avec au moins 1 ou 2 sprites référencés comme variables. Si je veux changer les sprites en adressables, dois-je changer les références en adressables une par une, ou existe-t-il une astuce pour le faire ?
A : Un script de l'éditeur est probablement la meilleure solution pour convertir ces références.

Vous pouvez ajouter les champs AssetReference à votre ScriptableObject (et conserver temporairement les champs Sprite). Vous pouvez ensuite écrire un script d'éditeur qui parcourt vos objets scriptables, recherche l'actif Sprite dans Addressables pour trouver l'entrée AddressableAssetEntry associée, et stocke l'adresse ou crée une AssetReference à stocker sur l'objet scriptable.

Enfin, vous pouvez supprimer les références directes aux sprites et remplacer tout code connexe par une référence aux actifs.

Q : Puis-je utiliser des objets adressables pour les jeux WebGL ? Dans l'affirmative, y a-t-il des éléments spécifiques à rechercher ?
A : Oui, et oui. Deux choses à noter : Tout d'abord, WebGL ne supporte pas le threading, donc n'utilisez pas les Tâches. Deuxièmement, la mise en cache fonctionne différemment sur WebGL - nous avons déjà vu des problèmes avec la mise en cache des AssetBundles distants.

Q : Si j'utilise Shader.Find("ShaderName"), cela vient-il de la construction ou des adressables ?
A : Ces données proviennent de la version du lecteur Unity, et non d'Addressables. Shader.Find() ne renvoie pas les résultats des AssetBundles.

Q : Comment organiser la fenêtre Groupes adressables lorsque j'ai plusieurs groupes portant des noms similaires ?
A : Pour organiser l'interface utilisateur des groupes d'adressables, vous pouvez activer l'option Hiérarchie des groupes avec tirets. Cela permet de regrouper les groupes portant des noms similaires. Par exemple, "Personnage-personne" et "Personnage-personne2" apparaîtront dans l'interface utilisateur sous le groupe "Personnage".

Cela n'a pas d'incidence sur la manière dont les liasses sont créées. Il ne s'agit que d'un changement organisationnel de l'assurance-chômage.

Faites-nous part de vos commentaires dans le forum Addressables. Ne manquez pas les nouveaux blogs techniques d'autres développeurs Unity dans le cadre de la série permanente Tech from the Trenches.