Profilage UI Unity: qui gâche mon lot?


Vous avez passé un temps infini à optimiser l'interface utilisateur Unity. Mais pour provoquer une inhibition, une petite modification du minuscule attribut de l'élément UI Canvas presque invisible suffit. Et lorsque cela se produit, même le profilage de l'interface utilisateur Unity ne vous évitera pas de réduire FPS. Êtes-vous prêt pour une longue correction de bogue?

C'est exactement ce qui s'est passé dans mon dernier projet ...

J'ai travaillé dur pour optimiser plusieurs panneaux d'interface utilisateur dans le port de notre jeu sur Oculus Quest . Fondamentalement, la tâche consistait à réduire le niveau d'overdraw à des valeurs acceptables afin que le GPU puisse faire face à la chose la plus importante - le vrai rendu 3D.

J'ai donc travaillé sur l'optimisation de l'interface utilisateur Unity pendant au moins un mois, et j'ai finalement fait des progrès sacrément bons.

À un moment donné, l'interface utilisateur est devenue tellement optimisée qu'elle a à peine affecté le timing du GPU. Les techniques de gradation de l'interface utilisateur opaque que j'ai implémentées ont compensé la plupart des redessins causés par la superposition de l'interface utilisateur (éléments dessinés au-dessus d'autres éléments).

J'ai donc obtenu un système d'interface utilisateur hybride hautement optimisé, qui chevauchait essentiellement les éléments 3D dessinés sous lui. Il est devenu très facile de supprimer le rendu de ces fragments superposés.

Cependant, le travail était encore loin d'être terminé ...

Lorsque j'ai branché le Unity UI Profiler , une chose a attiré mon attention.

J'ai vu qu'un processeur surchargé passe plus de 1 ms dans chaque trame pour rendre l'interface utilisateur. C'est beaucoup de temps pour une plateforme qui vous offre un budget de 13 ms pour l'ensemble du jeu: physique, logique, rendu 3D, entrée, VR et code réseau.

Et après tout, il y avait des cas où l'interface utilisateur «tuait» encore plus les performances du processeur.


Interface Unity: lots de construction coûteux

Et cela dit une chose: l' interface utilisateur peut être optimisée pour le GPU, mais cela ne signifie pas nécessairement une optimisation pour le CPU .

En fait, lors du rendu de l'interface utilisateur Unity, les tâches CPU et GPU sont très différentes. Sans surprise, je recommande d'approcher l'optimisation CPU et GPU différemment, et cela a été discuté dans mon post précédent sur l'optimisation de l'interface utilisateur Unity .

Un profilage plus poussé de l'interface utilisateur Unity a révélé un problème évident: l'interface utilisateur était constamment recréée dans chaque nouveau cadre, c'est-à-dire Canvas (Canvas Rebuild) a été reconstruit dans chaque cadre .

Charge constante sur le CPU pendant 1 ms ... oh-oh.

Mais pourquoi Unity me fait ça? Je pensais que Unity mettait en cache toutes les interfaces de Canvas ...

En fait, oui. Unity met efficacement en cache Canvas afin qu'ils ne soient collectés qu'une seule fois.

Cependant, le problème se pose lorsque vous modifiez les propriétés de l'un des éléments d'interface utilisateur dans le canevas - couleur, position, etc.

Autrement dit, toutes les animations que nous aimons, par exemple, les effets des boutons lorsque vous survolez, tuez la productivité, et vous ne le savez probablement pas.

Lorsqu'un changement de propriété d'interface utilisateur se produit, Unity exécute le célèbre Canvas Rebuild, qui ruine les performances du jeu .

La reconstruction du canevas de l'interface force le moteur Unity à parcourir de manière itérative tous les éléments d'interface utilisateur de ce canevas pour générer une liste optimisée d'appels de dessin (nombreux sommets, couleurs, matériaux, etc.). Et le Canvas Rebuild prend plus de temps que le Seat Panda prend pour accélérer de zéro à 60 mph .

Réalisant que nous souffrons constamment de Canvas Rebuild, il serait logique de poser une question ...

Pourquoi souffrons-nous des reconstructions de Canvas et que pouvons-nous faire?

Pour répondre à cette question simple, j'ai dû passer plus de 5 heures à étudier le sujet et à travailler avec le profileur UI Unity .

Faisons les choses correctement.

1. Profiling Unity UI: tout va bien, pour l'instant ...


Imaginez que nous ayons une interface utilisateur simple.

Cette interface utilisateur ne fait rien, elle apparaît simplement à l'écran et agace le joueur qui essaie de voir quelque chose à travers.

En tant qu'ensemble de plus de 350 images dans le groupe de disposition de grille, il ressemble à ceci:


Exemple de profilage de l'interface utilisateur Unity

Et tout est en ordre, malgré 350 images impaires. Dans le cas standard, l'interface utilisateur restituera en seulement deux appels de dessin, car il n'y a que deux images uniques qui ne sont pas dans l'atlas des sprites.

En fait, dans le profileur, je peux voir qu'il n'y a pratiquement pas de charge de la part du CPU. La plupart du temps passé sur l'interface utilisateur est inférieur à 0,01 ms , ce qui est plutôt bon.


Unity UI Profiling: A Mysterious Surge

(... la plupart du temps)

Attendez, d'où vient cette augmentation des ressources CPU à la fin du graphique?

2. Profilage de l'interface utilisateur Unity: reconstruction soudaine de la toile!


Que s'est-il passé à la fin du profil Unity? Très étrange, en seulement une seconde, la surcharge du processeur sur l'interface utilisateur Unity était plus du double.

Je veux jouer à un jeu

Trouvez les deux différences dans les exemples ci-dessous (vous devrez peut-être ouvrir les images dans une fenêtre séparée pour mieux voir) .


Profilage de l'interface utilisateur Unity: toile à faible coût


Profilage de l'interface utilisateur Unity: reconstruction

Je vous donne cinq secondes pour le comprendre.

5, 4 ... eh bien, voici une astuce pour simplifier la tâche:


Profilage de l'interface utilisateur Unity: Reconstruction du canevas aérien

Ouah!

PostLateUpdate.UpdateRectTransform et UGUI.Rendering.UpdateBatches veulent fortement devenir les principales stars de cette émission.

Que font ces domaines?

Le premier, UpdateRectTransform , indique clairement que la transformation de certains objets a changé, et donc Unity doit effectuer une logique coûteuse pour refléter les changements visuels. Nous ne savons pas s'il s'agissait d'une position, d'une rotation, d'une échelle ou d'une autre des propriétés de RectTransform .

Enfer, nous ne savons même pas si ce n'était qu'un seul attribut, ou tout à la fois. S'agissait-il d'un seul objet ou de plusieurs? Et lesquels? Voilà le problème: nous ne savons pas .

La deuxième pièce coûteuse, UpdateBatches , est liée à la nécessité de reconstruire toute la géométrie de Canvas. Ce processus est appelé Canvas Rebuild . La reconstruction de Canvas signifie que Unity parcourt toute la hiérarchie de Canvas pour générer une liste d'appels de dessin. Les sommets, les indices, les couleurs et les uv de tous les éléments sont calculés, puis une passe de passage est effectuée pour combiner le nombre maximal d'appels de tirage afin de réduire la charge inutile sur le processeur, en la passant au pilote graphique.

Maintenant, nous semblons savoir ce qui se passe et nous sommes sur la bonne voie. Mais comment éviter cette refonte de Canvas? Qu'est-ce qui les cause?

Nous avons besoin d'informations plus spécifiques ...

Pour résumer

  • La modification d'un attribut dans un élément d'interface utilisateur marque l'élément lui-même comme sale
  • L'élément d'interface utilisateur peut être complètement sale, mais il peut également être partiellement: dessus sales, disposition sale, matériaux sales. Il est plus facile de se remettre des états partiellement sales
  • Une fois tous les éléments Canvas marqués comme sales, Unity le reconstruit complètement
  • Les reconstructions de canevas sont coûteuses pour le CPU, donc la chose la plus importante à éviter est

3. À la recherche d'un ravageur: un moyen de force brute politiquement incorrect


Nous devons encore répondre à la question suivante:

Quelles sont les causes de ces reconstructions Canvas?

Il s'avère qu'il n'y a pas de moyen rapide de le savoir, en particulier avec une grande hiérarchie Canvas.

Mais d'abord, je vais vous montrer une méthode de force brute pour trouver la raison de Canvas Rebuild .


1. Laissez Unity UI Profiler continuer l'enregistrement

Nous filtrerons les statistiques afin de nous concentrer sur les plus importantes: le rendu, les scripts et l'interface utilisateur.

Suivez la marque initiale pour comprendre les coûts du schéma actuel, qui devrait inclure la reconstruction coûteuse de Canvas.


2. Désactivez les objets de jeu de l'interface utilisateur et comparez les lectures

Sélectionnez le groupe d'objets de jeu et désactivez-les.

Comparez les mesures de performances.

Si les lectures ne se sont pas beaucoup améliorées, continuez à désactiver les objets du jeu jusqu'à ce que vous constatiez une amélioration significative.


3. Trouvez ce qui change ses propriétés

Nous avons pu sélectionner l'objet qui appelle le Canvas Rebuild. Mais que devient exactement leur cause?

Peut-être que son échelle change à travers le script? Ou est-ce que sa position change par l'animation?

Il sera commode de faire un clic droit sur RectTransform et de sélectionner " Rechercher des références dans la scène "

Lorsque vous découvrez les causes de la reconstruction du canevas, faites quelque chose, par exemple, désactivez les animations ou les transformations.

Ruben, mais comment utiliser cette méthode avec une énorme hiérarchie d'interface utilisateur? Ne me dis pas de conneries

J'ai dit que le processus ne serait ni rapide ni intéressant, mais les joueurs vous en seraient reconnaissants.

Voilà le point. Premièrement, l'existence d'une énorme hiérarchie n'est pas une situation idéale. Ce sont des hiérarchies si massives et profondes qui rendent Canvas Rebuild si cher pour le processeur.

Mais des hiérarchies d'interface utilisateur grandes et imbriquées peuvent (et se produiront), alors attendez-vous à ce que la reconstruction de toile touche le plus important: le gameplay.

Bien que la méthode de la force brute aide à trouver la source de la révision de Canvas, elle ne se transforme pas bien à long terme.

Devenu plus professionnel dans l'optimisation de l'interface utilisateur, j'ai créé un outil qui donne toutes les réponses dont j'ai besoin pour que le projet réponde aux attentes des acteurs ...


Reconstruction de la toile de profilage

4. Bonus: amélioration des fonctionnalités d'optimisation de l'interface utilisateur de Unity Profiler


J'espère que vous comprenez déjà à quel point la reconstruction de Canvas peut être fréquente et dérangeante.

Cette perestroïka, qui a infecté mon jeu, a emporté jusqu'à 10% du budget CPU total!

Comme nous l'avons vu, il existe une méthode de force brute pour trouver les sources de Canvas Rebuild. Vous pouvez peut-être les gérer en utilisant les stratégies répertoriées dans mon article sur l' optimisation de l'interface utilisateur Unity .

Mais un tel processus sujet aux erreurs ne satisferait jamais un vrai gourou. Vous pouvez passer quelques jours à vous battre avec Canvas Rebuild, mais au moment le plus inattendu, ils reviendront disparaître dès que vous brancherez le profileur d'interface utilisateur Unity.

Si vous développez un jeu pour VR, cela devient critique. Nous ne voulons pas que Canvas soit reconstruit dans l'interface utilisateur de l'espace mondial. Si vous ne pouvez pas vous débarrasser de la perestroïka, vos joueurs ne le supporteront probablement pas.

D'accord, j'ai l'idée de me débarrasser de Canvas Rebuilds. Mais Unity Profiler ne fournit presque aucune information à leur sujet! Que pouvez-vous conseiller?

Heureux que vous ayez demandé. Il s'avère que nous pouvons convaincre Unity Profiler de nous fournir des informations utiles sur ce qui entrave les performances de l'interface utilisateur .

Nous pouvons étendre les fonctionnalités de Unity UI Profiler . Pour ce faire, vous devez modifier le code source de l'interface utilisateur Unity disponible publiquement. Une fois que vous arrivez au code source, vous devrez trouver les fonctions de code dans lesquelles les reconstructions de toile se produisent . Ensuite, nous avons besoin de magie API avec BeginSample et EndSample profiler .

Si vous exécutez Unity 2019.1 ou une version antérieure, le code source de l'interface utilisateur Unity a été téléchargé dans le référentiel Bitbucket . Il existe également un guide de téléchargement, d'installation et de modification.

Que dois-je conseiller? Utilisez une version plus récente d'Unity, pas inférieure à 2019.2.0. Les versions plus récentes d'Unity sont fournies par défaut avec l'interface utilisateur source , car le système d'interface utilisateur fait désormais partie du gestionnaire de packages. C'est le moyen le plus simple.

Voici une liste de morceaux de code que j'ai découvert au cours de mes recherches où je peux ajouter des appels d'API de profilage:



Interface utilisateur Unity: source de profilage

Est-ce utile? Oui

Pratique pour l'artiste / designer? Non.

C'est le poète qui a écrit la petite extension Unity open source qui étend les capacités de l'Unity Profiler .


Cet outil gratuit nous permettra de basculer rapidement entre les différents modes de profilage pour assurer des performances de jeu maximales.

Quelle est la meilleure chose à propos de ce module d'extension Unity Profiler? Il fonctionne en dehors de l'éditeur, vous soulageant essentiellement de tous les maux de tête lors du profilage de l'interface utilisateur pour Android et d'autres plates-formes.

La voici, toute sa puissance est contrôlée par seulement deux boutons:

  • Buff my Unity Profiler
  • Nerf my Unity Profiler .

Vous pouvez obtenir cet outil ici .

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


All Articles