Optimisation de l'interface utilisateur Unity

image


Cet article traite de l'optimisation des éléments d'interface utilisateur des projets réalisés dans Unity. Sur la base d'informations issues de la documentation officielle et de mon expérience personnelle, j'ai essayé d'expliquer clairement les principes de fonctionnement des éléments de l'interface utilisateur. Vous trouverez également ici des conseils pratiques qui vous aideront à améliorer les performances de votre projet en ce qui concerne l'interface utilisateur.



Terminologie


Les éléments d'interface utilisateur sont tous les éléments d'Unity liés à la création d'une interface utilisateur. Cela inclut, par exemple: bouton, texte, image, menu déroulant, etc.
Canvas (canvas) - l'élément de base de l'interface utilisateur, qui est un conteneur pour le reste des éléments.
Mesh - un ensemble de paramètres décrivant un modèle 3D.
Un quad est un maillage qui est un quadrilatère.
Batching - combinaison de maillages d'objets en un seul grand maillage pour un rendu plus rapide.
Draw-call - une commande pour dessiner du moteur vers l'API graphique (par exemple, OpenGL ou Direct3D).
File d'attente transparente - une file d'attente pour le rendu d'objets transparents.
Alpha blending (Alpha blending) - un algorithme pour mélanger les pixels sur le canal alpha pour obtenir une image avec transparence.
Atlas est un type de ressource qui combine plusieurs textures en une seule.


Introduction


Dans l'optimisation de l'interface utilisateur, il n'y a pas de règles universelles qui fonctionnent dans n'importe quelle situation. Tout se résume à trouver un équilibre entre le coût du traitement par lots et le nombre d'appels de tirage. On peut distinguer quatre problèmes principaux:


  • Charge GPU trop élevée (surcharge sur le rendu);
  • trop de charge CPU lors de la reconstruction du canevas;
  • trop d'éléments changeants conduisant à la reconstruction de la toile;
  • La charge du processeur est trop importante pour la génération de maillage (généralement associée au texte).

Rendu de l'interface utilisateur Unity


L'élément de base de l'interface utilisateur Unity est le canevas. Il est responsable de la génération, du tri et du rendu des maillages des éléments d'interface enfant. Tous les éléments de l'interface utilisateur doivent être des enfants de n'importe quel canevas, sinon ils ne seront pas affichés dans le jeu.
image
Le rendu se produit de l'objet le plus éloigné à l'objet le plus éloigné de l'appareil photo (de l'arrière vers l'avant) dans la file d' attente transparente avec un mélange alpha.


Par ailleurs, il convient de noter que la transparence des éléments de l'interface utilisateur n'affecte PAS les performances. Même si l'élément est entièrement constitué de pixels «opaques», il sera toujours rendu en utilisant le mélange alpha.


Il est également important de comprendre que lors du rendu, tous les pixels de tous les éléments actifs sont traités. Cela ne dépend pas qu’ils soient visibles, bloqués par d’autres objets ou même complètement transparents.


Refonte de l'interface utilisateur


La refonte de l'interface utilisateur est un processus en plusieurs étapes, comprenant la construction des maillages de chaque élément de l'interface utilisateur et la tentative de patcher ces maillages afin de minimiser le nombre d' appels de tirage .


La reconstruction se déroule en quatre étapes:


  1. Les structures des éléments sont analysées.
  2. Les maillages de tous les éléments actifs, y compris les éléments avec une transparence nulle, sont reconstruits.
  3. Reconstruit les matériaux pour le maillage des maillages d'éléments.
  4. Tous les éléments sont dessinés selon leur ordre.

Le canevas reconstruit est mis en cache et réutilisé jusqu'à ce que l'un des éléments du canevas soit marqué comme modifié.
Les objets sales sont marqués qui ont été activés ou désactivés; qui ont changé de matière, de position, d'échelle, de rotation; la valeur du texte du composant texte a changé; réaffectation du parent, etc.


Dans ce cas, la reconstruction du canevas contient à nouveau au moins un élément modifié. Certes, cela s'applique uniquement au canevas dans lequel se trouve l'élément. En d'autres termes, les modifications apportées aux éléments dans les toiles enfants n'affectent pas celles des parents.


Plus il y a d'éléments dans le canevas, plus le coût d'analyse et de tri des objets est élevé.


Maillage


La fusion de maillages ou de lots permet de réduire la charge sur le GPU en réduisant le nombre d'appels de tirage. Au cours du processus de traitement par lots, les mailles sont triées par profondeur et vérifiées pour le chevauchement. Lors du passage d'un élément distant à un élément proche (ou de l'élément supérieur à l'élément inférieur dans la hiérarchie), les objets avec les mêmes matériaux ou textures sont combinés en un maillage au sein du même canevas. Pour cela, il ne doit pas y avoir d'objets avec d'autres matériaux entre eux. En outre, les objets avec d'autres matériaux ne doivent pas chevaucher les objets cuits au four avec leurs conteneurs globaux. L'opération de traitement par lots est multi-thread, ses performances varient considérablement en fonction du nombre de cœurs dans le processeur.


Le texte peut flotter avec d'autres textes s'ils ont la même police. Peu importe que les paramètres et les styles de police soient identiques ou différents. Si les polices sont différentes, le texte ne roulera pas.


Il convient également de garder à l'esprit que le texte peut chevaucher un objet avec son conteneur global, et un tel chevauchement peut être facilement ignoré.
image


Prenons un exemple. Il y a trois objets A, B et C disposés dans une hiérarchie de cette façon:
image
image
Dans l'image de gauche, les objets A et C seront fusionnés, car ont le même matériau et ne se croisent pas avec l'objet B. Dans l'image de droite, les objets A et C ne seront pas combinés, car il y a une intersection avec l'objet B.


Conseils généraux d'optimisation de l'interface utilisateur


Avant de commencer l'optimisation, il est fortement recommandé de profiler l'interface utilisateur. Cela aidera à identifier les goulots d'étranglement entraînant une perte de performances (le cas échéant). Pour le profilage, il existe de nombreux outils, à la fois intégrés à Unity (Unity Profiler) et à des outils tiers. Mais nous ne discuterons pas des problèmes de profilage de l'interface utilisateur dans cet article.


Voici quelques suggestions pour optimiser votre interface utilisateur dans Unity:


  1. Désactivez les objets invisibles. Si un élément est superposé par un élément opaque, vous devez désactiver son GameObject ou le GameObject parent de l'élément superposé. Dans le même temps, les éléments d'interface avec alpha défini sur 0 seront toujours dessinés. Pour de tels objets, vous devez activer Cull Transparent Mesh dans le composant Canvas Renderer ou tout simplement désactiver les objets invisibles.
    image
  2. Désactivez les objets du monde cachés par une interface opaque. Si l'interface ne couvre pas le monde entier, vous pouvez l'enregistrer dans la texture de rendu et désactiver la caméra mondiale.
  3. Minimisez le nombre de pixels à dessiner. Combinez autant d'images que possible en une seule. Par exemple, il est logique de faire des boutons un sprite unique, plutôt que des calques séparés avec un arrière-plan, un trait, un corps de bouton, etc. Cela réduira la flexibilité de travailler avec de tels éléments et peut entraîner un colmatage des ressources, donc un compromis doit être recherché.
    image
  4. Évitez les éléments vides qui servent uniquement à organiser la structure (n'utilisez pas les éléments comme noms de «dossiers» dans la hiérarchie des documents).
  5. Évitez de croiser des objets qui ne peuvent pas cuire les uns avec les autres. Si possible, il est préférable de modifier la position dans la hiérarchie, la taille du conteneur ou la position des éléments qui se chevauchent et qui n'agglomèrent pas.
  6. Utilisez un canevas séparé ou imbriqué pour les éléments dynamiques. Vous minimisez ainsi le coût du tri et de la reconstruction de la structure du canevas contenant un grand nombre d'éléments. Les toiles imbriquées sont plus pratiques, car hérite des paramètres du canevas parent. Dans le même temps, lors du changement du canevas parent, tous ceux imbriqués seront également reconstruits. C'est assez rare, mais cela arrive (par exemple, lors du changement de la résolution d'écran). Gardez à l'esprit que les objets provenant de différentes toiles ou de toiles imbriquées NE sont PAS cuits pour le rendu conjoint. Il est recommandé de diviser les toiles selon la régularité des éléments de mise à jour. Les éléments statiques doivent être placés dans un canevas séparé, puis ils ne seront dessinés qu'une seule fois. S'il y a des éléments qui changent constamment, il est préférable de les combiner dans un autre canevas, car ils continueront à se reconstruire. Les objets changeants peuvent également être divisés en plusieurs toiles par le taux de rafraîchissement. Par exemple, les éléments mis à jour à chaque cadre sont placés dans un canevas et les éléments mis à jour moins souvent dans un autre.
  7. La désactivation de Pixel Perfect augmentera considérablement la productivité. Cela est particulièrement vrai pour les objets constamment mis à jour avec un grand nombre d'éléments (par exemple, un inventaire défilant).
    image
    La toile
    image
    Toile imbriquée
  8. Si vous devez désactiver le canevas, ne désactivez pas l'objet qui le contient (via la fonction SetActive ). La prochaine fois que vous activerez les éléments de ce canevas, ils seront marqués comme modifiés et tous les éléments seront reconstruits. Il est préférable de désactiver le composant de canevas lui-même, alors la structure entière et les données cuites ne changeront pas et la prochaine fois que vous activerez le composant de canevas, ils commenceront simplement leur dessin.
  9. Pour les toiles avec Screen Space - Camera ou World Space sélectionné dans le paramètre Render Mode , installez toujours une caméra. Si vous ne l'installez pas, le système d'interface utilisateur dans chaque cadre le recherchera via Object.FindObjectWithTag pour trouver Camera.main , et cela affectera les performances.
  10. Afin de ne pas créer plusieurs textures identiques, vous pouvez en créer une en nuances de gris et la «peindre» via le composant Image en sélectionnant la couleur souhaitée.
  11. Ne laissez l' indicateur Raycast Target que sur les éléments qui nécessitent des événements d'entrée et supprimez le reste. Par défaut, la cible Raycast est activée sur de nombreux éléments (image, texte, etc.). Cela complique et ralentit le travail du composant Raycaster , qui gère les événements d'entrée dans Unity UI. Lorsque vous cliquez ou appuyez sur, il parcourt toute la hiérarchie des éléments et recherche tous les composants graphiques avec l' indicateur Raycast Target défini, puis les vérifie pour la possibilité d'événements d'entrée et, après avoir passé les vérifications avec succès, les ajoute à la liste des résultats. Après cela, la liste des résultats est triée par profondeur, les objets en dehors de l'écran sont supprimés. En conséquence, il donne la liste finale des résultats.
    Dans Unity UI, de nombreux composants (Image, Texte, etc.) ont l' indicateur Raycast Target .

image
Raycast Target sur le composant image.


image
TextMeshPro l'a caché dans l'onglet Paramètres supplémentaires .


image
Pour TextMeshPro, vous pouvez définir le paramètre Cible Raycast par défaut dans Paramètres du lecteur -> TextMest Pro -> Paramètres -> Activer la cible Raycast .


Les éléments sont testés lorsque:


  • Raycast Target activé
  • l'élément lui-même est allumé et activé;
  • le point d'insertion est à l'intersection avec RectTransform.

Il est également judicieux de supprimer l'indicateur Raycast Target des enfants si l'objet racine le possède déjà et chevauche complètement les enfants avec sa géométrie. Par exemple, le bouton d'interface utilisateur Unity standard.



L'image chevauche complètement le texte avec sa forme, dans ce cas, vous pouvez supprimer la cible Raycast du composant texte.



Si tous les éléments du canevas n'attendent pas les événements d'entrée, vous pouvez supprimer le composant Graphic Raycaster du canevas / canevas imbriqué.


Travailler avec du texte et son optimisation


Le texte de l'interface Unity est constitué de grilles dans lesquelles chaque symbole est créé son propre quad. Le maillage est reconstruit à chaque fois que la valeur du texte change. La reconstruction se produit également si le composant texte ou son parent a été désactivé puis réactivé.


Par défaut, les polices dans Unity sont ajoutées en tant que dynamiques. Pour chaque police dynamique utilisée dans le composant texte de la scène, un atlas est créé. Seuls les personnages utilisés sont inclus dans cet atlas. Par exemple, si le champ de texte contient le texte «Nouveau texte», l'atlas créé pour lui contiendra les caractères «N», «e», «w», «T», «x» et «t». Pour chaque personnage de taille ou de style différent, une représentation sera créée dans l'atlas.



Texte sur scène



Atlas des polices


Si pendant l'exécution du programme le contenu du composant texte change et qu'il apparaît des caractères qui ne sont pas dans l'atlas, l'atlas entier sera reconstruit. S'il y a de l'espace libre dans la texture de l'atlas, les symboles nécessaires y seront simplement ajoutés. Dans le même temps, les caractères qui ne sont pas actuellement utilisés ne seront pas supprimés. S'il n'y a pas assez d'espace dans l'atlas pour de nouveaux caractères, sa taille sera doublée et remplie à nouveau en fonction des caractères utilisés dans les composants de texte actifs.


Si un nombre strictement défini de caractères est défini pour un projet, par exemple, uniquement l'alphabet latin, alors il vaut la peine d'utiliser des polices statiques qui sont stockées en permanence en mémoire. Si votre projet autorise un grand nombre de caractères, il vaut mieux s'attarder sur les polices dynamiques.
Vous pouvez également améliorer les performances en remplaçant le composant texte par un sprite. Par exemple, les nombres apparaissant dans le jeu (score) peuvent être créés à l'aide de sprites d'un atlas contenant uniquement un ensemble de caractères nécessaires. Dans ce cas, il n'y aura aucun frais pour reconstruire la toile et l'atlas de la police.


L'utilisation de polices de secours, répertoriées dans le champ Noms des polices des paramètres de police, augmente la mémoire utilisée. Cela est particulièrement visible dans les polices pictographiques.


Il n'est pas recommandé d'utiliser Best Fit , car cette option entraîne un débordement rapide de l'atlas et provoque sa restructuration.
Le meilleur ajustement ignore les paramètres de taille de police et essaie d'ajuster le texte dans le rectangle de contour du composant texte.


Maintenant, quelques mots sur TextMeshPro (TMP) , un remplacement populaire pour le composant texte Unity standard. TextMeshPro reconstruit également sa grille à chaque fois que la valeur du texte change. Cependant, le texte TMP n'utilise pas de polices dynamiques. Pour cela, des atlas de polices sont générés à l'avance, qui incluent tous les caractères nécessaires. Si, pour certains textes de la scène, aucun caractère de la police n'est affecté à son composant, alors TMP commence la recherche dans les polices de sauvegarde. S'il n'y a rien, alors TMP essaiera de trouver ce caractère dans toutes les polices téléchargées.


Best Fit in TMP ne crée pas de problèmes comme un composant de texte normal, il peut donc être utilisé.


Un grand nombre de polices avec différentes localisations ou de grands atlas de polices peuvent occuper beaucoup de mémoire. Par conséquent, il est préférable d'utiliser le préchargement uniquement les polices nécessaires à une localisation spécifique.


World Space recommande d'utiliser TextMeshPro au lieu de TextMeshProUGUI .
TextMeshProUGUI est utilisé dans les toiles.


Atlas de sprites


Les atlas de sprites sont un type de ressource qui combine plusieurs textures en une seule. Ils vous permettent de réduire le nombre de tirages ( appels de tirage ) et d'augmenter la productivité.


Création d'atlas.
Créez un atlas: Actif> Créer> Sprite Atlas .
Sélectionnez l'atlas et placez le sprite nécessaire dans Objects for Packing .
image
Cliquez sur Aperçu du pack pour prévisualiser l'atlas.
image
Gardez à l'esprit que même si un ou plusieurs sprites de l'atlas sont utilisés sur la scène, l'atlas sera toujours chargé dans son intégralité. Par conséquent, cela n'a aucun sens d'essayer d'incorporer toutes les images dans un atlas géant, qui sur les appareils avec une petite RAM peut prendre sa partie tangible. Il vaut mieux percer quelques atlas plus petits, par exemple, l'atlas de l'interface utilisateur du menu du jeu et l'atlas de l'interface du mode jeu.


Évitez les grands espaces vides dans l'atlas, afin de ne pas occuper trop d'espace mémoire. Pour ce faire, vous pouvez redimensionner l'atlas ou ajouter des images supplémentaires pour remplir autant que possible l'espace vide.
image
image
Pour les images qui ne sont pas dans l'atlas, vous devez sélectionner les paramètres corrects.
Pour chaque format de compression, il existe des exigences en vertu desquelles il fonctionnera efficacement. Les exigences d'image les plus courantes:


  • la largeur et la hauteur doivent être un multiple de la puissance de deux;
  • la largeur et la hauteur doivent être un multiple de 4;
  • les deux paragraphes précédents ensemble.
    Sinon, la texture ne sera pas compressée et des coûts supplémentaires de mémoire de périphérique se produiront.

Lors du choix d'un format de compression, Unity vous indiquera si les exigences pour le format sélectionné ne sont pas remplies.
image


N'oubliez pas non plus que les formats sont différents de l'appareil cible. Pour plus d'informations et de recommandations sur les formats, consultez la documentation officielle :


Résumer les méthodes d'optimisation


  • Désactiver les objets invisibles et transparents
  • Minimisez le nombre d'articles
  • Évitez de traverser des objets qui ne peuvent pas cuire les uns avec les autres
  • Distribuer des éléments par toile en fonction du taux de rafraîchissement
  • Pour les toiles avec des éléments fréquemment mis à jour, désactivez Pixel Perfect
  • Désactiver Raycast Target sur les éléments non cliquables
  • Supprimez le composant Graphic Raycaster du canevas pour lequel tous les éléments ne sont pas cliquables
  • Pour les composants de texte normaux, n'utilisez pas Best Fit
  • Pour TextMeshPro Dans World Space, utilisez TextMeshPro au lieu de TextMeshProUGUI. TextMeshProUGUI utilisé dans les toiles
  • Réglez l'appareil photo dans les paramètres du canevas, si nécessaire
  • Désactivez le canevas en désactivant le composant canevas
  • Utilisez des sprites en niveaux de gris et colorisez les paramètres du composant d'image
  • Utilisez des atlas de sprites
  • Utilisez la taille et le format de compression corrects pour les textures absentes de l'atlas

Sources:


Informations complètes sur l'optimisation de l'interface utilisateur Unity


Une autre source officielle sur ce sujet contient des informations sous une forme plus concise.


Livres blancs Atlas


Informations supplémentaires sur les formats de compression de texture

Source: https://habr.com/ru/post/fr470608/


All Articles