
Optimisation des performances pour des graphismes haut de gamme sur PC et console
Ceci est le deuxième d'une série d'articles qui décompose les conseils d'optimisation pour vos projets Unity. Utilisez-les comme guide pour fonctionner à des taux de rafraîchissement plus élevés avec moins de ressources. Une fois que vous avez essayé ces meilleures pratiques, assurez-vous de consulter les autres pages de la série :
Les outils graphiques de Unity vous permettent de créer des graphismes optimisés dans n'importe quel style, sur une gamme de plateformes – des mobiles aux consoles haut de gamme et aux ordinateurs de bureau. Ce processus dépend généralement de votre direction artistique et de votre pipeline de rendu, donc avant de commencer, nous vous recommandons de consulter les Pipelines de rendu disponibles.

Rendu en avant
Lors du choix d'un pipeline de rendu, prenez ces considérations en compte. En plus de choisir un pipeline, vous devrez sélectionner un chemin de rendu.
Le chemin de rendu représente une série spécifique d'opérations liées à l'éclairage et à l'ombrage. Le choix d'un chemin de rendu dépend des besoins et du matériel cible de votre application.
Chemin de rendu en avant
Le rendu en avant est utilisé à la fois dans le Pipeline de rendu universel (URP) et le Pipeline de rendu intégré. Dans le rendu en avant, la carte graphique projette la géométrie et la divise en sommets. Ces sommets sont ensuite décomposés en fragments, ou pixels, qui sont rendus à l'écran, créant l'image finale.
Le pipeline passe chaque objet, un à la fois, à l'API graphique. Le rendu en avant a un coût pour chaque lumière, donc plus il y a de lumières dans votre scène, plus le rendu prendra de temps.
Le Rendu en avant du pipeline intégré dessine chaque lumière dans un passage séparé par objet. Si plusieurs lumières touchent le même GameObject, cela peut créer un surdessin significatif où les zones qui se chevauchent doivent dessiner le même pixel plus d'une fois. Pour réduire le surdessin, minimisez le nombre de lumières en temps réel.
Plutôt que de rendre un passage par lumière, l'URP élimine les lumières par objet. Cela permet de calculer l'éclairage en un seul passage, ce qui entraîne moins d'appels de dessin par rapport au Rendu en avant du Pipeline de rendu intégré.

Rendu différé
Le Pipeline de rendu intégré, l'URP et le Pipeline de rendu haute définition (HDRP) utilisent également le chemin de rendu d'ombrage différé. Dans l'ombrage différé, l'éclairage n'est pas calculé par objet.
Au lieu de cela, le rendu différé reporte le rendu lourd, tel que l'éclairage, à une étape ultérieure et utilise deux passes. Dans la première passe, également appelée la passe de géométrie G-buffer, Unity rend les GameObjects. Cette passe récupère plusieurs types de propriétés géométriques et les stocke dans un ensemble de textures.
Les textures G-buffer peuvent inclure :
- Couleurs diffuse et spéculaire
- Lissage de surface
- Occlusion
- Normales en espace monde
- Émission + ambiant + réflexions + lightmaps
Dans la deuxième passe, ou passe d'éclairage, Unity rend l'éclairage de la scène basé sur le G-buffer. Imaginez itérer sur chaque pixel et calculer les informations d'éclairage en fonction du tampon au lieu des objets individuels. Ajouter plus de lumières qui ne projettent pas d'ombre dans le rendu différé n'entraîne pas la même perte de performance qu'avec le rendu direct.
Bien que le choix d'un chemin de rendu ne soit pas exactement une optimisation en soi, cela peut affecter la façon dont vous optimisez votre projet. Les autres techniques et flux de travail dans cette section varient en fonction du pipeline de rendu et du chemin que vous sélectionnez.

Graphiques de shaders
À la fois HDRP et URP prennent en charge Shader Graph, une interface visuelle basée sur des nœuds pour la création de shaders. Elle permet aux utilisateurs sans expérience en programmation de shaders de créer des effets d'ombrage complexes.
Plus de 150 nœuds sont actuellement disponibles dans Shader Graph. De plus, vous pouvez créer vos propres nœuds personnalisés avec l'API.
Chaque shader dans un Shader Graph commence par un Master Node, qui détermine la sortie du graph. Construisez la logique du shader en ajoutant et en connectant des nœuds et des opérateurs dans l'interface visuelle.
Le Shader Graph passe ensuite dans l'arrière-plan du pipeline de rendu. Le résultat final est un shader ShaderLab qui est fonctionnellement similaire à un écrit en HLSL ou Cg.
L'optimisation d'un Shader Graph suit de nombreuses règles similaires à celles qui s'appliquent aux shaders HLSL ou Cg traditionnels ; l'une des plus importantes étant que plus votre Shader Graph effectue de traitements, plus cela impactera les performances de votre application.
Si vous êtes limité par le CPU, l'optimisation de vos shaders n'améliorera pas le taux de rafraîchissement, mais cela pourrait améliorer la durée de vie de votre batterie pour les plateformes mobiles.
Si vous êtes limité par le GPU, suivez ces directives pour améliorer les performances avec Shader Graph :
Supprimez les nœuds inutilisés : Ne changez aucun paramètre par défaut ou ne connectez pas de nœuds à moins que ces changements ne soient nécessaires. Le Shader Graph compile automatiquement toutes les fonctionnalités inutilisées. Lorsque cela est possible, intégrez des valeurs dans des textures. Par exemple, au lieu d'utiliser un nœud pour éclaircir une texture, appliquez la luminosité supplémentaire dans l'actif de texture lui-même.
Utilisez un format de données plus petit lorsque cela est possible : Envisagez d'utiliser Vector2 au lieu de Vector3, ou de réduire la précision (par exemple, demi au lieu de float), si votre projet le permet.
Réduisez les opérations mathématiques : Les opérations de shader s'exécutent de nombreuses fois par seconde, essayez donc d'optimiser les opérateurs mathématiques lorsque cela est possible. Visez à mélanger les résultats au lieu de créer une branche logique. Utilisez des constantes et combinez des valeurs scalaires avant d'appliquer des vecteurs. Enfin, convertissez toutes les propriétés qui n'ont pas besoin d'apparaître dans l'Inspecteur en nœuds en ligne. Toutes ces améliorations incrémentielles peuvent aider votre budget de trame.
Branchez un aperçu : À mesure que votre graphique devient plus grand, il peut devenir plus lent à compiler. Simplifiez votre flux de travail avec une branche séparée et plus petite contenant uniquement les opérations que vous souhaitez prévisualiser à ce moment. Ensuite, itérez plus rapidement sur cette branche plus petite jusqu'à ce que vous obteniez les résultats souhaités. Si la branche n'est pas connectée au Master Node, vous pouvez laisser en toute sécurité la branche de prévisualisation dans votre graphique. Unity supprime les nœuds qui n'affectent pas la sortie finale lors de la compilation.
Optimiser manuellement : Même les programmeurs graphiques expérimentés peuvent encore utiliser un Shader Graph pour poser du code standard pour un shader basé sur un script. Sélectionnez l'actif Shader Graph, puis sélectionnez Copier le shader dans le menu Contexte. Créez un nouveau shader HLSL/Cg, puis collez le Shader Graph copié. C'est une opération unidirectionnelle, mais cela vous permet d'optimiser les performances avec des optimisations manuelles.

Supprimer les paramètres de shader intégrés
Supprimez tous les shaders inutilisés de la liste appelée Always Included Shaders, qui se trouve dans les paramètres Graphiques (Modifier > Paramètres du projet > Graphiques). Ajoutez ici tous les shaders nécessaires pour la durée de vie de l'application.
Éliminer les variantes de shader
Utilisez les directives pragma de compilation de shader pour adapter la compilation d'un shader à chaque plateforme cible. Utilisez ensuite un mot-clé de shader (ou un nœud Shader Graph keyword) pour créer des variantes de shader avec certaines fonctionnalités activées ou désactivées.
Les variantes de shader peuvent être utiles pour des fonctionnalités spécifiques à la plateforme, mais augmentent également les temps de construction et la taille des fichiers. Vous pouvez empêcher les variantes de shader d'être incluses dans votre construction si vous savez qu'elles ne sont pas nécessaires.
Tout d'abord, analysez le Editor.log pour le timing et la taille des shaders. Ensuite, localisez les lignes qui commencent par Shader compilé et Shader compressé.
Ce journal d'exemple montre les statistiques suivantes :
Shader compilé 'TEST Standard (configuration spéculaire)' en 31,23s
d3d9 (programmes internes totaux : 482, unique : 474)
d3d11 (programmes internes totaux : 482, unique : 466)
metal (programmes internes totaux : 482, unique : 480)
glcore (programmes internes totaux : 482, unique : 454)
Shader compressé 'TEST Standard (configuration spéculaire)' sur d3d9 de 1,04 Mo à 0,14 Mo
Shader compressé 'TEST Standard (configuration spéculaire)' sur d3d11 de 1,39 Mo à 0,12 Mo
Shader compressé 'TEST Standard (configuration spéculaire)' sur metal de 2,56 Mo à 0,20 Mo
Shader compressé 'TEST Standard (configuration spéculaire)' sur glcore de 2,04 Mo à 0,15 Mo
Ces statistiques vous disent quelques choses sur le shader :
- Il s'étend en 482 variantes en raison de la #pragma multi_compile et shader_feature.
- Unity compresse le shader inclus dans les données du jeu à peu près à la somme des tailles compressées : 0,14+0,12+0,20+0,15 = 0,61 MO.
- Au moment de l'exécution, Unity garde les données compressées en mémoire (0,61 Mo), tandis que les données pour votre API graphique actuellement utilisée restent non compressées. Par exemple, si votre API actuelle est Metal, cela représenterait 2,56 Mo.
Après une construction, le Project Auditor (expérimental) peut analyser le Editor.log pour afficher une liste de tous les shaders, mots-clés de shader et variantes de shader compilés dans le projet. Il peut également analyser le Player.log après l'exécution du jeu. Cela vous montre quelles variantes l'application a réellement compilées et utilisées au moment de l'exécution.
Utilisez ces informations pour construire un système de suppression de shader scriptable et réduire le nombre de variantes. Cela peut améliorer les temps de construction, les tailles de construction et l'utilisation de la mémoire à l'exécution.
Lisez l'article Sur le script de variantes de shaders à supprimer pour voir ce processus en détail.

Lisser les bords avec l'anti-aliasing
L'anticrénelage contribue à une qualité d'image plus nette en réduisant les bords dentelés et en minimisant l'aliasing spéculaire.
Si vous utilisez le rendu Forward avec le pipeline de rendu intégré, l'anticrénelage par échantillonnage multiple (MSAA) est disponible dans les paramètres Qualité. Le MSAA produit un anticrénelage de haute qualité, mais peut être coûteux. Le paramètre appelé Nombre d'échantillons MSAA dans le menu déroulant définit combien d'échantillons le moteur de rendu utilise pour évaluer l'effet (Aucun, 2X, 4X, 8X). Si vous utilisez le rendu Forward avec URP ou HDRP, vous pouvez activer le MSAA sur l'Actif URP ou l'Actif HDRP respectivement.
Alternativement, vous pouvez ajouter l'anticrénelage comme effet de post-traitement. Cela apparaît sur le composant Caméra (sous Anticrénelage) avec quelques options :
- Anticrénelage approximatif rapide (FXAA) lisse les bords au niveau des pixels. C'est le type d'anticrénelage le moins gourmand en ressources. Il floute légèrement l'image finale.
- Anticrénelage morphologique sous-pixel (SMAA) mélange les pixels en fonction des bords d'une image. Il offre des résultats beaucoup plus nets que le FXAA et convient aux styles artistiques plats, de type cartoon ou propres.
Dans HDRP, vous pouvez également utiliser FXAA et SMAA dans l'Anticrénelage de post-traitement sur la caméra avec une option supplémentaire :
- Anticrénelage temporel (TAA) lisse les bords en utilisant des images du tampon d'historique. Cela fonctionne plus efficacement que le FXAA mais nécessite des vecteurs de mouvement pour fonctionner. Le TAA peut également améliorer l'occlusion ambiante et les volumétriques. Il est généralement de meilleure qualité que le FXAA, mais nécessite des ressources supplémentaires et peut produire des artefacts de fantôme occasionnels.

Cuisiner les lightmaps
L'option la plus rapide pour créer un éclairage est celle qui n'a pas besoin d'être calculée par image. Utilisez Lightmapping pour cuire l'éclairage statique une seule fois, au lieu de le calculer en temps réel.
Ajoutez un éclairage dramatique à votre géométrie statique en utilisant Global Illumination (GI). Cochez l'option Contribute GI pour que les objets stockent un éclairage de haute qualité sous forme de lightmaps.
Le processus de génération d'un environnement lightmapé prend plus de temps que de simplement placer une lumière dans la scène, mais il offre des avantages clés tels que :
- Fonctionnant deux ou trois fois plus vite pour des lumières à deux pixels
- Visuels améliorés via l'Illumination Globale, qui peut calculer un éclairage direct et indirect réaliste, tandis que le lightmapper lisse et réduit le bruit de la carte résultante
- Les ombres et l'éclairage cuits se rendent sans la perte de performance qui résulte généralement de l'éclairage et des ombres en temps réel
Des scènes plus complexes peuvent nécessiter de longs temps de cuisson. Si votre matériel prend en charge le Progressive GPU Lightmapper (en aperçu), cette option peut accélérer considérablement la génération de votre lightmap en utilisant le GPU au lieu du CPU.
Suivez ce guide pour commencer avec le Lightmapping dans Unity.

Minimiser les probes de réflexion
Bien que Reflection Probes puisse créer des réflexions réalistes, elles peuvent être coûteuses en termes de lots. Ainsi, essayez ces conseils d'optimisation pour minimiser l'impact sur la performance :
- Utilisez des cubemaps basse résolution, des masques de culling et une compression de texture pour améliorer la performance à l'exécution.
- Utilisez Type : Cuit pour éviter les mises à jour par image.
- Si l'utilisation de Type : En temps réel est nécessaire dans URP, essayez d'éviter Every Frame autant que possible. Ajustez le Mode de rafraîchissement et les Découpage temporel paramètres pour réduire le taux de mise à jour. Vous pouvez également contrôler le rafraîchissement avec l'option Via Scripting et rendre la sonde à partir d'un script personnalisé.
- Si l'utilisation de Type : Le temps réel est nécessaire dans HDRP, sélectionnez le mode À la demande . Vous pouvez également modifier les Paramètres Cadre dans Paramètres du projet > Paramètres par défaut HDRP .
- Réduisez la qualité et les fonctionnalités sous Réflexion en temps réel pour améliorer les performances.

Désactiver les ombres
La diffusion d'ombres peut être désactivée par Mesh Renderer et lumière. Désactivez les ombres chaque fois que possible pour réduire les requêtes. Vous pouvez également créer de fausses ombres en utilisant une texture floue appliquée à un maillage simple ou un quad sous vos personnages. Sinon, vous pouvez créer des ombres de blob avec des shaders personnalisés.
En particulier, évitez d'activer les ombres pour les Lumières ponctuelles . Chaque lumière ponctuelle avec des ombres nécessite six passes de carte d'ombre par lumière – comparez cela à une seule passe de carte d'ombre pour une Lumière spot . Envisagez de remplacer les lumières ponctuelles par des lumières spot lorsque des ombres dynamiques sont absolument nécessaires. Si vous pouvez éviter les ombres dynamiques, utilisez un cubemap comme un Light.cookie avec vos lumières ponctuelles à la place.
Substituer un effet de shader
Dans certains cas, vous pouvez appliquer des astuces simples plutôt que d'ajouter plusieurs lumières supplémentaires. Par exemple, au lieu de créer une lumière qui brille directement dans la caméra pour donner un effet d'éclairage de contour, utilisez un shader pour simuler Éclairage de contour (voir Surface Shader exemples pour une implémentation de cela en HLSL).

Utiliser des couches de lumière
Pour des scènes complexes avec de nombreuses lumières, séparez vos objets en utilisant des couches, puis confinez l'influence de chaque lumière à un Masque de gommage spécifique.

Utilisez les Light Probes
Les sondes lumineuses stockent des informations d'éclairage cuites sur l'espace vide de votre scène, tout en fournissant un éclairage de haute qualité (à la fois direct et indirect). Ils utilisent sphères harmoniques, qui se calculent rapidement par rapport aux lumières dynamiques. Ceci est particulièrement utile pour les objets en mouvement, qui ne peuvent normalement pas recevoir de Baked Lightmapping.
Les Light Probes peuvent également s'appliquer aux maillages statiques. Dans le composant Mesh Renderer, localisez le menu déroulant Receive Global Illumination et basculez-le de Lightmaps à Light Probes.
Continuez à utiliser le Lightmapping pour votre géométrie de niveau proéminente, mais passez aux Light Probes pour éclairer les petits détails. L'illumination par Light Probe ne nécessite pas de UV appropriés, vous évitant ainsi l'étape supplémentaire de dépliage de vos maillages. Les Probes réduisent également l'espace disque car elles ne génèrent pas de textures Lightmap.
Voir le post Static lighting with Light Probes, ainsi que Making believable visuals in Unity pour plus d'informations.

L'un de nos guides les plus complets à ce jour recueille plus de 80 conseils pratiques sur la façon d'optimiser vos jeux pour PC et console. Créés par nos ingénieurs experts en succès et en Accelerate Solutions, ces conseils approfondis vous aideront à tirer le meilleur parti de Unity et à améliorer les performances de votre jeu.