L'utilisation de la mémoire est essentielle dans le développement de jeux Android. Lorsque vous développez des jeux à l'aide d'Unreal Engine, vous devez analyser et suivre en permanence l'état de la mémoire pour respecter ces contraintes, en évitant les fuites de mémoire et les allocations excessives.
Économies de mémoire grâce à la réduction des permutations de nuanceurs
En supprimant les options inutilisées dans Lighting ou Mobile Shader Permutation
Reduction, vous pouvez réduire le nombre de permutations de nuanceurs. Cela réduit considérablement la taille du package de l'application, diminue le nombre d'objets d'état de pipeline (PSO) et empêche la création de cibles de rendu ou de textures factices inutilisées, ce qui réduit la mémoire d'exécution et améliore les performances.
Pour en savoir plus, consultez la section Misc Lighting and Shader Permutation Reduction Settings for Mobile (Paramètres divers d'éclairage et de réduction des permutations de nuanceurs pour mobile) dans les consignes de performances pour les appareils mobiles.
Optimisation du chargement des composants
Lorsque vous chargez des composants à l'aide de références matérielles, le contenu connecté qui n'est même pas utilisé dans le jeu est chargé simultanément en mémoire, ce qui entraîne une consommation de mémoire inutile. En particulier, lorsque l'héritage est mal utilisé dans les Blueprints, des CDO (objets par défaut de classe) inutiles provenant des parents sont alloués, ce qui gaspille une quantité importante de mémoire. Dans ce cas, appliquez les techniques suivantes pour optimiser l'utilisation de la mémoire.
- Définition du code C++ et séparation des données : définissez les fonctionnalités de base
à l’aide de
UCLASS(Abstract)dans le code C++, en les séparant des données réelles. - Réduisez l'héritage : effectuez la configuration des données et le chargement des composants uniquement dans les Blueprints des nœuds feuilles.
- Utilisez des références indirectes : appliquez des références de propriétés indirectes à l'aide de
TSoftObjectPtrpour éviter les références matérielles et chargez les composants de manière asynchrone uniquement lorsque cela est nécessaire au moment de l'exécution. - Précautions : lorsque vous utilisez le chargement asynchrone des composants, assurez-vous que des vérifications de validité
(
IsValid) sont effectuées lors du rappel de fin de chargement pour éviter les pointeurs suspendus ou les plantages.
Pour en savoir plus, consultez Référencer des composants et créer des jeux mobiles avec UE5.
Réglage des pointeurs intelligents et de la récupération de mémoire (GC)
L'utilisation de pointeurs intelligents (tels que TSharedPtr et TWeakPtr) lors du développement en C++ empêche les pointeurs suspendus et les fuites de mémoire. De plus, l'utilisation de TWeakPtr évite de créer des références fortes aux objets. Ainsi, le garbage collector n'incrémente pas les nombres de références lors de la collecte d'objets. Cela évite la survie inutile des objets et réduit la complexité du graphique de référence que le GC doit parcourir, ce qui réduit considérablement la surcharge du GC. La récupération de mémoire peut être gérée efficacement dans les environnements mobiles en déclenchant ForceGarbageCollection lors des transitions de niveau ou des périodes d'inactivité, par exemple lorsqu'il n'y a aucune interaction de l'utilisateur. De plus, elle peut être déclenchée lorsque le jeu est dans un état perceptible ou en arrière-plan (par exemple, les rappels onStop), ce qui garantit que la récupération de mémoire est effectuée sans affecter l'expérience de jeu active.
Pour en savoir plus, consultez Récupération de mémoire et pointeur intelligent.
Optimisation à l'aide de la compression de la table de relocalisation
La compression de la table de relocalisation est une méthode d'optimisation qui compresse la taille de la table de relocalisation dans les binaires ELF pour réduire la taille des binaires Android. Lorsque la valeur minSDKVersion d'Android est égale ou supérieure à 23, la compression de la table de relocalisation APS est prise en charge. Lorsque la valeur minSDKVersion est égale ou supérieure à 28, la compression de la table de relocalisation RELR est également prise en charge, ce qui réduit considérablement la taille du fichier .so. Cela réduit non seulement la taille du téléchargement, mais aussi l'espace mémoire utilisé du mmap .so au moment de l'exécution, ce qui atténue la pression globale sur la mémoire physique.
AndroidToolChain.cs
if (MinSDKVersion >= 28)
{
Result += " -Wl,--pack-dyn-relocs=android+relr,--use-android-relr-tags";
}
else if (MinSDKVersion >= 23)
{
Result += " -Wl,--pack-dyn-relocs=android";
}
Pour appliquer cette optimisation, vérifiez que l'option Enable compression of relocation tables (Activer la compression des tables de relocalisation) est activée dans les paramètres du projet ou que la variable bEnableAdvancedBinaryCompression est activée.
Pour vérifier si la compression RELR est correctement appliquée au binaire, utilisez l'outil llvm-readelf du NDK Android.
llvm-readelf -d libUnreal.so | grep RELR
En pratique, la création du modèle ThirdPerson d'Unreal Engine et la mesure à l'aide de dumpsys meminfo confirment une réduction de l'utilisation de PSS et de RSS pour le mmap .so.
| Catégorie | PSS (total) | Private Dirty | Private Clean | Swap Dirty | RSS (total) |
|---|---|---|---|---|---|
| mmap .so Avant compression | 170 210 | 24 360 | 141 564 | 0 | 242 204 |
| mmap .so Après compression | 138 031 | 24 748 | 108 976 | 0 | 210 140 |
Compression de texture
Utilisez une compression de texture appropriée pour réduire l'encombrement mémoire des ressources graphiques globales. L'utilisation de la compression de textures Adaptive Scalable Texture Compression (ASTC), la norme mobile, offre une qualité visuelle supérieure à celle d'ETC2 pour la même taille, ou permet d'obtenir des taux de compression plus élevés avec une consommation de mémoire inférieure pour le même objectif de qualité visuelle.
Optimisation du streaming de textures
Dans les environnements mobiles, l'utilisation directe de la taille du pool de streaming de textures par défaut d'Unreal Engine peut préallouer un pool de mémoire excessivement volumineux par rapport aux spécifications de l'appareil. Il est donc idéal de définir des profils d'appareils mobiles et de sélectionner une taille de pool de streaming de textures appropriée en fonction des limites de mémoire de l'appareil. Utilisez également la fonctionnalité Statistic (Statistiques) de l'éditeur pour vérifier les statistiques des textures et identifier les textures qui consomment beaucoup de mémoire et qui occupent des résolutions extrêmes au moment de l'exécution. Associez cette fonctionnalité à la fonctionnalité Required Texture Resolution (Résolution de texture requise) pour appliquer des limites ou réduire les résolutions maximales sur les textures exigeantes, en maintenant l'utilisation des ressources sous contrôle dans le tampon de mémoire de texture alloué.