Recommandations sur les performances pour UnityPerformance recommendations for Unity

Cet article s’appuie sur les recommandations relatives aux performances pour la réalité mixte, mais il se concentre sur les améliorations propres à Unity.This article builds on the performance recommendations for mixed reality, but focuses on Unity-specific improvements.

Pour optimiser les performances des applications de réalité mixte dans Unity, la première étape, et la plus importante, consiste à utiliser les paramètres d’environnement recommandés pour Unity.The most important first step when optimizing performance of mixed reality apps in Unity is to be sure you're using the recommended environment settings for Unity. Le contenu de cet article s’intéresse à certaines des configurations de scène les plus importantes pour créer des applications Mixed Reality performantes.That article contains content with some of the most important scene configurations for building performant Mixed Reality apps. Certains de ces paramètres recommandés sont également soulignés ci-après.Some of these recommended settings are highlighted below, as well.

Comment profiler avec UnityHow to profile with Unity

Unity est fourni avec le profileur intégré Unity Profiler , qui constitue une ressource intéressante pour recueillir de précieux insights sur les performances de votre application.Unity provides the Unity Profiler built-in, which is a great resource to gather valuable performance insights for your particular app. Bien qu’il soit possible d’exécuter le profileur dans l’éditeur, ces métriques ne représentent pas l’environnement d’exécution réel et vous devez donc en utiliser les résultats avec prudence.Although you can run the profiler in-editor, these metrics don't represent the true runtime environment so results should be used cautiously. Nous vous recommandons de profiler à distance votre application pendant son exécution sur un appareil pour obtenir des insights plus précis et exploitables.We recommended remotely profiling your application while running on device for most accurate and actionable insights. De plus, le débogueur Frame Debugger d’Unity est également un puissant outil d’analyse à votre disposition.Further, Unity's Frame Debugger is also a powerful and insight tool to use.

Unity fournit une documentation très dense sur les thèmes suivants :Unity provides great documentation for:

  1. Comment connecter à distance le profileur Unity à des applications UWPHow to connect the Unity profiler to UWP applications remotely
  2. Comment diagnostiquer efficacement les problèmes de performances avec Unity ProfilerHow to effectively diagnose performance problems with the Unity Profiler

Notes

Une fois Unity Profiler connecté et après avoir ajouté le profileur GPU (consultez Ajouter un profileur dans le coin supérieur droit), vous pouvez voir le temps passé sur le processeur et le GPU respectivement au milieu du profileur.With the Unity Profiler connected and after adding the GPU profiler (see Add Profiler in top right corner), one can see how much time is being spent on the CPU & GPU respectively in the middle of the profiler. Ainsi, le développeur détermine approximativement et rapidement si son application est liée au processeur ou au GPU.This allows the developer to get a quick approximation if their application is CPU or GPU bounded.

Processeur et GPU Unity

Recommandations sur les performances de processeurCPU performance recommendations

Le contenu ci-dessous couvre des pratiques liées aux performances de manière plus approfondie, en ciblant particulièrement le développement en C# avec Unity.The content below covers more in-depth performance practices, especially targeted for Unity & C# development.

Mettre en cache les référencesCache references

Nous vous recommandons de mettre en cache les références à tous les composants et GameObjects pertinents lors de l’initialisation, car les appels de fonction répétitifs, tels que GetComponent<T>() et Camera.main sont plus coûteux par rapport au coût de mémoire pour stocker un pointeur.We recommend caching references to all relevant components and GameObjects at initialization because repeating function calls such as GetComponent<T>() and Camera.main are more expensive relative to the memory cost to store a pointer. .. Camera.main utilise simplement FindGameObjectsWithTag () , qui recherche de façon coûteuse dans votre graphe de scène un objet caméra portant l’étiquette « MainCamera » .Camera.main just uses FindGameObjectsWithTag() underneath, which expensively searches your scene graph for a camera object with the "MainCamera" tag.

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
    private Camera cam;
    private CustomComponent comp;

    void Start() 
    {
        cam = Camera.main;
        comp = GetComponent<CustomComponent>();
    }

    void Update()
    {
        // Good
        this.transform.position = cam.transform.position + cam.transform.forward * 10.0f;

        // Bad
        this.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 10.0f;

        // Good
        comp.DoSomethingAwesome();

        // Bad
        GetComponent<CustomComponent>().DoSomethingAwesome();
    }
}

Notes

Éviter GetComponent(string)Avoid GetComponent(string)
Quand vous utilisez GetComponent() , il existe plusieurs surcharges différentes.When using GetComponent(), there are a handful of different overloads. Il est important de toujours utiliser les implémentations basées sur le type et jamais la surcharge de recherche basée sur la chaîne.It is important to always use the Type-based implementations and never the string-based searching overload. Une recherche par chaîne dans votre scène est beaucoup plus coûteuse qu’une recherche par type.Searching by string in your scene is significantly more costly than searching by Type.
(Correct) Component GetComponent(Type type)(Good) Component GetComponent(Type type)
(Good) T GetComponent<T>()(Good) T GetComponent<T>()
(Mauvais) Component GetComponent(string)>(Bad) Component GetComponent(string)>

Éviter les opérations coûteusesAvoid expensive operations

  1. Éviter l’utilisation de LINQAvoid use of LINQ

    Même si LINQ est très propre et facile à lire et à écrire, cette technologie nécessite généralement plus de calcul et de mémoire que l’écriture manuelle de l’algorithme.Although LINQ can be clean and easy to read and write, it generally requires more computation and memory than if you wrote the algorithm manually.

    // Example Code
    using System.Linq;
    
    List<int> data = new List<int>();
    data.Any(x => x > 10);
    
    var result = from x in data
                 where x > 10
                 select x;
    
  2. API Unity courantesCommon Unity APIs

    Certaines API Unity, bien qu’utiles, peuvent s’avérer onéreuses à exécuter.Certain Unity APIs, although useful, can be expensive to execute. La plupart d’entre elles impliquent la recherche d’une liste de GameObjects correspondante dans l’ensemble de votre graphe de scène.Most of these involve searching your entire scene graph for some matching list of GameObjects. Ces opérations peuvent généralement être évitées en mettant en cache les références ou en implémentant un composant de gestionnaire pour les GameObjects afin de suivre les références au moment de l’exécution.These operations can generally be avoided by caching references or implementing a manager component for the GameObjects to track the references at runtime.

        GameObject.SendMessage()
        GameObject.BroadcastMessage()
        UnityEngine.Object.Find()
        UnityEngine.Object.FindWithTag()
        UnityEngine.Object.FindObjectOfType()
        UnityEngine.Object.FindObjectsOfType()
        UnityEngine.Object.FindGameObjectsWithTag()
        UnityEngine.Object.FindGameObjectsWithTag()
    

Notes

SendMessage() et BroadcastMessage() doivent être éliminés à tout prix.SendMessage() and BroadcastMessage() should be eliminated at all costs. Ces fonctions peuvent être de l’ordre de 1 000 fois plus lentes que les appels de fonction directs.These functions can be on the order of 1000x slower than direct function calls.

  1. Attention à BoxingBeware of boxing

    Boxing est un concept fondamental du langage et runtime C#.Boxing is a core concept of the C# language and runtime. Il s’agit du processus qui consiste à wrapper des variables de type valeur, par exemple char, int, bool, etc., dans des variables de type référence.It's the process of wrapping value-typed variables such as char, int, bool, etc. into reference-typed variables. Quand une variable de type valeur fait l’objet d’un « boxing », elle est wrappée dans un System.Object stocké sur le tas managé.When a value-typed variable is "boxed", it's wrapped in a System.Object, which is stored on the managed heap. De la mémoire est allouée et, quand elle est supprimée, elle doit être traitée par le garbage collector.Memory is allocated and eventually when disposed must be processed by the garbage collector. Ces allocations et désallocations entraînent un coût pour les performances et, dans de nombreux scénarios, s’avèrent inutiles ou peuvent être facilement remplacées par une alternative moins coûteuse.These allocations and deallocations incur a performance cost and in many scenarios are unnecessary or can be easily replaced by a less expensive alternative.

    Pour éviter le boxing, vérifiez que les variables, les champs et les propriétés dans lesquels vous stockez des types numériques et des structs (notamment Nullable<T>) sont fortement typés en tant que types spécifiques comme int, float? ou MyStruct au lieu d’utiliser l’objet.To avoid boxing, be sure that the variables, fields, and properties in which you store numeric types and structs (including Nullable<T>) are strongly typed as specific types such as int, float? or MyStruct, instead of using object. Si vous placez ces objets dans une liste, veillez à utiliser une liste fortement typée telle que List<int> au lieu de List<object> ou ArrayList.If putting these objects into a list, be sure to use a strongly typed list such as List<int> rather than List<object> or ArrayList.

    Exemple de boxing en C#Example of boxing in C#

    // boolean value type is boxed into object boxedMyVar on the heap
    bool myVar = true;
    object boxedMyVar = myVar;
    

Chemins de code répétitifsRepeating code paths

Toutes les fonctions de rappel Unity répétitives (c.-à-d.Any repeating Unity callback functions (i.e Update) exécutées plusieurs fois par seconde et/ou image doivent être écrites soigneusement.Update) that are executed many times per second and/or frame should be written carefully. Toutes les opérations coûteuses ont ici un impact énorme et constant sur les performances.Any expensive operations here will have huge and consistent impact on performance.

  1. Fonctions de rappel videsEmpty callback functions

    Bien que le code ci-dessous puisse vous paraître inoffensif si vous le laissez dans votre application, notamment parce que chaque script Unity s’initialise automatiquement avec une méthode de mise à jour, ces rappels vides peuvent devenir coûteux.Although the code below may seem innocent to leave in your application, especially since every Unity script auto-initializes with an Update method, these empty callbacks can become expensive. Unity fonctionne en alternance entre une limite de code non managé et managé, entre le code UnityEngine et votre code d’application.Unity operates back and forth between an unmanaged and managed code boundary, between UnityEngine code and your application code. Le changement de contexte sur ce pont est assez onéreux, même s’il n’y a rien à exécuter.Context switching over this bridge is fairly expensive, even if there's nothing to execute. Cela devient particulièrement problématique si votre application comporte des centaines de GameObjects avec des composants qui ont des rappels Unity répétitifs vides.This becomes especially problematic if your app has 100s of GameObjects with components that have empty repeating Unity callbacks.

    void Update()
    {
    }
    

Notes

Update() est la manifestation la plus courante de ce problème de performances, mais d’autres rappels Unity répétitifs, comme les suivants peuvent s’avérer aussi mauvais, si ce n’est pire : FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), etc.Update() is the most common manifestation of this performance issue but other repeating Unity callbacks, such as the following can be equally as bad, if not worse: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), etc.

  1. Opérations dont l’exécution une fois par frame est à privilégierOperations to favor running once per frame

    Les API Unity suivantes sont des opérations courantes pour de nombreuses applications holographiques.The following Unity APIs are common operations for many Holographic Apps. Bien que cela ne soit pas toujours possible, les résultats de ces fonctions peuvent être souvent calculés une seule fois et les résultats réutilisés dans l’application pour une image donnée.Although not always possible, the results from these functions can commonly be computed once and the results reutilized across the application for a given frame.

    a) Une bonne pratique consiste à avoir une classe ou un service Singleton dédié(e) pour gérer votre Raycast de pointage du regard dans la scène, puis à réutiliser ce résultat dans tous les autres composants de scène, au lieu d’effectuer des opérations Raycast répétées et identiques.a) It's good practice to have a dedicated Singleton class or service to handle your gaze Raycast into the scene and then reuse this result in all other scene components, instead of making repeated and identical Raycast operations by each component. Certaines applications peuvent nécessiter des raycasts provenant de différentes origines ou sur différents LayerMasks.Some applications may require raycasts from different origins or against different LayerMasks.

        UnityEngine.Physics.Raycast()
        UnityEngine.Physics.RaycastAll()
    

    b) Évitez les opérations GetComponent() dans les rappels Unity répétés comme Update() en mettant en cache les références dans Start() ou Awake().b) Avoid GetComponent() operations in repeated Unity callbacks like Update() by caching references in Start() or Awake()

        UnityEngine.Object.GetComponent()
    

    c) Une bonne pratique consiste à instancier tous les objets, si possible, lors de l’initialisation et à utiliser la mise en pool d’objets pour recycler et réutiliser les GameObjects tout au long de l’exécution de votre applicationc) It's good practice to instantiate all objects, if possible, at initialization and use object pooling to recycle and reuse GameObjects throughout runtime of your application

        UnityEngine.Object.Instantiate()
    
  2. Éviter les interfaces et les constructions virtuellesAvoid interfaces and virtual constructs

    L’invocation d’appels de fonction par le biais d’interfaces plutôt que d’objets directs ou l’appel de fonctions virtuelles peuvent souvent s’avérer beaucoup plus coûteux que l’utilisation de constructions directes ou d’appels de fonction directs.Invoking function calls through interfaces vs direct objects or calling virtual functions can often be much more expensive than using direct constructs or direct function calls. Si la fonction virtuelle ou interface n’est pas nécessaire, elle doit être supprimée.If the virtual function or interface is unnecessary, then it should be removed. Toutefois, la baisse de performances dans ces approches est plus intéressante si leur utilisation simplifie la collaboration pour le développement, la lisibilité du code et la maintenabilité du code.However, the performance hit for these approaches is worth the trade-off if using them simplifies development collaboration, code readability, and code maintainability.

    En règle générale, il est recommandé de ne pas marquer des champs et des fonctions comme virtuels, sauf s’il est clairement attendu que ce membre a besoin d’être remplacé.Generally, the recommendation is to not mark fields and functions as virtual unless there's a clear expectation that this member needs to be overwritten. Une attention particulière doit être portée aux chemins de code à haute fréquence qui sont appelés de nombreuses fois par frame, ou même une seule fois par frame, comme une méthode UpdateUI().One should be especially careful around high-frequency code paths that are called many times per frame or even once per frame such as an UpdateUI() method.

  3. Éviter de passer des structs par valeurAvoid passing structs by value

    Contrairement aux classes, les structs sont des types valeur et quand ils sont passés directement à une fonction, leur contenu est copié dans une instance nouvellement créée.Unlike classes, structs are value-types and when passed directly to a function, their contents are copied into a newly created instance. Cette copie augmente le coût du processeur, ainsi que la mémoire supplémentaire sur la pile.This copy adds CPU cost, as well as additional memory on the stack. Pour les petits structs, l’effet est minime et donc acceptable.For small structs, the effect is minimal and thus acceptable. En revanche, pour les fonctions appelées à plusieurs reprises, chaque frame ainsi que les fonctions acceptant des grands structs, modifiez si possible la définition de fonction pour qu’elle passe par référence.However, for functions repeatedly invoked every frame as well as functions taking large structs, if possible modify the function definition to pass by reference. En savoir plus iciLearn more here

DiversMiscellaneous

  1. PhysiquePhysics

    a) En règle générale, le moyen le plus simple d’améliorer la physique consiste à limiter le temps dédié à la physique ou le nombre d’itérations par seconde.a) Generally, the easiest way to improve physics is to limit the amount of time spent on Physics or the number of iterations per second. La précision de la simulation s’en trouve réduite.This will reduce simulation accuracy. Consultez TimeManager dans Unity.See TimeManager in Unity

    b) Les types des colliders dans Unity possèdent des caractéristiques de performances très différentes.b) The types of colliders in Unity have widely different performance characteristics. Les colliders ci-dessous sont listés du plus performant au moins performant, de gauche à droite.The order below lists the most performant colliders to least performant colliders from left to right. Il est important d’éviter les Mesh Colliders, qui sont beaucoup plus onéreux que les colliders primitifs.It's important to avoid Mesh Colliders, which are substantially more expensive than the primitive colliders.

    Sphère < Capsule < Boîte <<< Maillage (convexe) < Maillage (non-convexe)Sphere < Capsule < Box <<< Mesh (Convex) < Mesh (non-Convex)

    Pour plus d’informations, consultez Bonnes pratiques pour la physique dans Unity.See Unity Physics Best Practices for more info

  2. AnimationsAnimations

    Désactivez les animations inactives en désactivant le composant Animator (la désactivation de l’objet jeu n’a pas le même effet).Disable idle animations by disabling the Animator component (disabling the game object won't have the same effect). Évitez les modèles de conception où un animateur se trouve dans une boucle qui affecte une valeur à la même chose.Avoid design patterns where an animator sits in a loop setting a value to the same thing. Cette technique présente une surcharge considérable, sans effet sur l’application.There's considerable overhead for this technique, with no effect on the application. En savoir plus ici.Learn more here.

  3. Algorithmes complexesComplex algorithms

    Si votre application utilise des algorithmes complexes comme des cinématiques inverses, des recherches de chemins, etc., recherchez une approche plus simple ou ajustez les paramètres pertinents pour leurs performances.If your application is using complex algorithms such as inverse kinematics, path finding, etc, look to find a simpler approach or adjust relevant settings for their performance

Recommandations sur les performances de processeur à GPUCPU-to-GPU performance recommendations

En règle générale, les performances de processeur à GPU diminuent jusqu’aux appels de dessin soumis à la carte graphique.Generally, CPU-to-GPU performance comes down to the draw calls submitted to the graphics card. Pour améliorer les performances, les appels de dessin doivent être stratégiquement a) réduits ou b) restructurés afin d’obtenir des résultats optimaux.To improve performance, draw calls need to be strategically a) reduced or b) restructured for optimal results. Étant donné que les appels de dessin eux-mêmes sont gourmands en ressources, leur réduction réduira le travail global nécessaire.Since draw calls themselves are resource-intensive, reducing them will reduce overall work required. De plus, les changements d’état entre les appels de dessin nécessitent des étapes de validation et de traduction coûteuses dans le pilote graphique et, par conséquent, la restructuration des appels de dessin de votre application pour limiter les changements d’état (c.-à-d.Further, state changes between draw calls require costly validation and translation steps in the graphics driver and thus, restructuring of your application's draw calls to limit state changes (i.e les différents matériaux, etc.) peuvent améliorer les performances.different materials, etc) can boost performance.

Unity dispose d’un excellent article qui donne une vue d’ensemble descriptive du traitement par lot des appels de dessin pour sa plateforme.Unity has a great article that gives an overview and dives into batching draw calls for their platform.

Rendu d’instance à passage uniqueSingle pass instanced rendering

Le rendu d’instance à passage unique dans Unity permet de réduire les appels de dessin pour chaque œil à un seul appel de dessin instancié.Single Pass Instanced Rendering in Unity allows for draw calls for each eye to be reduced down to one instanced draw call. En raison de la cohérence du cache entre deux appels de dessin, les performances sont également améliorées sur le GPU.Because of cache coherency between two draw calls, there's also some performance improvement on the GPU as well.

Pour activer cette fonctionnalité dans votre projet UnityTo enable this feature in your Unity Project

  1. Ouvrez Player XR Settings (accédez à Edit > Project Settings > Player > XR Settings).Open Player XR Settings (go to Edit > Project Settings > Player > XR Settings)
  2. Sélectionnez Single Pass Instanced dans le menu déroulant Stereo Rendering Method (la case Virtual Reality Supported doit être cochée).Select Single Pass Instanced from the Stereo Rendering Method drop-down menu (Virtual Reality Supported checkbox must be checked)

Lisez les articles suivants sur Unity pour plus d’informations sur l’approche de ce rendu.Read the following articles from Unity for details with this rendering approach.

Notes

Un problème courant avec le rendu d’instance à passage unique se produit si les développeurs ont déjà des nuanceurs personnalisés existants non écrits pour l’instanciation.One common issue with Single Pass Instanced Rendering occurs if developers already have existing custom shaders not written for instancing. Une fois cette fonctionnalité activée, les développeurs peuvent remarquer que certains GameObjects ne sont rendus que dans un seul œil.After enabling this feature, developers may notice some GameObjects only render in one eye. Cela est dû au fait que les nuanceurs personnalisés associés n’ont pas les propriétés appropriées pour l’instanciation.This is because the associated custom shaders do not have the appropriate properties for instancing.

Consultez Single Pass Stereo Rendering for HoloLens sur Unity pour savoir comment résoudre ce problème.See Single Pass Stereo Rendering for HoloLens from Unity for how to address this problem

Traitement par lot statiqueStatic batching

Unity est capable de traiter par lot de nombreux objets statiques pour réduire les appels de dessin au GPU.Unity is able to batch many static objects to reduce draw calls to the GPU. Le traitement par lot statique fonctionne pour la plupart des objets Renderer dans Unity qui 1) partagent le même matériau et 2) sont tous marqués comme statiques (sélectionnez un objet dans Unity et cochez la case en haut à droite de l’inspecteur).Static Batching works for most Renderer objects in Unity that 1) share the same material and 2) are all marked as Static (Select an object in Unity and select the checkbox in the top right of the inspector). Les GameObjects marqués comme statiques ne peuvent pas être déplacés dans le runtime de votre application.GameObjects marked as Static cannot be moved throughout your application's runtime. Ainsi, le traitement par lot statique peut s’avérer difficile à exploiter sur HoloLens, où pratiquement tous les objets ont besoin d’être placés, déplacés, mis à l’échelle, etc. Pour les casques immersifs, le traitement par lot statique peut réduire considérablement les appels de dessin et donc améliorer les performances.Thus, static batching can be difficult to leverage on HoloLens where virtually every object needs to be placed, moved, scaled, etc. For immersive headsets, static batching can dramatically reduce draw calls and thus improve performance.

Pour plus d’informations, consultez Traitement par lot statique sous Traitement par lot des appels de dessin dans Unity.Read Static Batching under Draw Call Batching in Unity for more details.

Traitement par lot dynamiqueDynamic batching

Étant donné qu’il est difficile de marquer des objets comme statiques pour le développement HoloLens, le traitement par lot dynamique peut s’avérer un excellent outil pour compenser cette fonctionnalité manquante.Since it's problematic to mark objects as Static for HoloLens development, dynamic batching can be a great tool to compensate for this lacking feature. Il peut également s’avérer utile sur les casques immersifs.It can also be useful on immersive headsets, as well. Toutefois, le traitement par lot dynamique dans Unity peut être difficile à activer car les GameObjects doivent a) partager le même matériau et b) remplir une longue liste d’autres critères.However, dynamic batching in Unity can be difficult to enable because GameObjects must a) share the same Material and b) meet a long list of other criteria.

Lisez Traitement par lot dynamique sous Traitement par lot des appels de dessin dans Unity pour obtenir la liste complète.Read Dynamic Batching under Draw Call Batching in Unity for the full list. En règle générale, les GameObjects deviennent non valides pour le traitement par lot dynamique, car les données de maillage associées ne peuvent pas dépasser 300 vertex.Most commonly, GameObjects become invalid to be batched dynamically, because the associated mesh data can be no more than 300 vertices.

Autres techniquesOther techniques

Le traitement par lot ne peut se produire que si plusieurs GameObjects sont en mesure de partager le même matériau.Batching can only occur if multiple GameObjects are able to share the same material. En règle générale, il est bloqué par la nécessité pour les GameObjects d’avoir une texture unique pour leur matériau respectif.Typically, this will be blocked by the need for GameObjects to have a unique texture for their respective Material. Il est courant de combiner des textures en une seule texture globale, une méthode appelée création d’un atlas de textures.It's common to combine Textures into one big Texture, a method known as Texture Atlasing.

En outre, il est préférable de combiner les maillages en un seul GameObject, lorsque cela est possible et raisonnable.Furthermore, it's preferable to combine meshes into one GameObject where possible and reasonable. Chaque convertisseur dans Unity a ses appels de dessin associés au lieu d’envoyer un maillage combiné sous un seul convertisseur.Each Renderer in Unity will have its associated draw call(s) versus submitting a combined mesh under one Renderer.

Notes

La modification des propriétés de Renderer.material au moment de l’exécution crée une copie du matériau et, par conséquent, interrompt éventuellement le traitement par lot.Modifying properties of Renderer.material at runtime will create a copy of the Material and thus potentially break batching. Utilisez Renderer.sharedMaterial pour modifier les propriétés des matériaux partagés entre les GameObjects.Use Renderer.sharedMaterial to modify shared material properties across GameObjects.

Recommandations sur les performances de GPUGPU performance recommendations

Découvrez-en plus sur l’optimisation du rendu graphique dans Unity.Learn more about optimizing graphics rendering in Unity

Optimiser le partage du tampon de profondeurOptimize depth buffer sharing

Il est recommandé d’activer Depth buffer sharing sous Player XR Settings pour optimiser la stabilité des hologrammes.It's recommended to enable Depth buffer sharing under Player XR Settings to optimize for hologram stability. En revanche, quand vous activez la reprojection au stade tardif basée sur la profondeur avec ce paramètre, il est recommandé de sélectionner le format de profondeur 16 bits au lieu du format de profondeur 24 bits.When enabling depth-based late-stage reprojection with this setting however, it's recommended to select 16-bit depth format instead of 24-bit depth format. Les tampons de profondeur 16 bits réduisent considérablement la bande passante (et donc la puissance) associée au trafic du tampon de profondeur.The 16-bit depth buffers will drastically reduce the bandwidth (and thus power) associated with depth buffer traffic. Cela peut s’avérer avantageux à la fois en termes de réduction de puissance et d’amélioration des performances.This can be a big win both in power reduction and performance improvement. Toutefois, il existe deux résultats négatifs possibles avec l’utilisation du format de profondeur 16 bits.However, there are two possible negative outcomes by using 16-bit depth format.

Z-FightingZ-Fighting

La fidélité à une plage de profondeur réduite rend le z-fighting plus susceptible de se produire avec 16 bits qu’avec 24 bits.The reduced depth range fidelity makes z-fighting more likely to occur with 16 bit than 24-bit. Pour éviter ces artefacts, modifiez les plans de découpage proche/lointain de la caméra Unity pour tenir compte de cette moindre précision.To avoid these artifacts, modify the near/far clip planes of the Unity camera to account for the lower precision. Pour les applications HoloLens, un plan de découpage lointain de 50 m au lieu des 1 000 m par défaut d’Unity peut en général éliminer tout z-fighting.For HoloLens-based applications, a far clip plane of 50 m instead of the Unity default 1000 m can generally eliminate any z-fighting.

Tampon de gabarit désactivéDisabled Stencil Buffer

Quand Unity crée une texture de rendu avec une profondeur de 16 bits, aucun tampon de gabarit n’est créé.When Unity creates a Render Texture with 16-bit depth, there's no stencil buffer created. La sélection du format de profondeur 24 bits, conformément à la documentation Unity, va créer un tampon z-buffer de 24 bits, ainsi qu’un [tampon de gabarit de 8 bits] (https://docs.unity3d.com/Manual/SL-Stencil.html) (si 32 bits sont applicables sur un appareil, ce qui est généralement le cas, notamment pour HoloLens).Selecting 24-bit depth format, per Unity documentation, will create a 24-bit z-buffer, as well as an [8-bit stencil buffer] (https://docs.unity3d.com/Manual/SL-Stencil.html) (if 32-bit is applicable on a device, which is generally the case such as HoloLens).

Éviter les effets plein écranAvoid full-screen effects

Les techniques qui fonctionnent en mode plein écran peuvent être coûteuses, car leur ordre de grandeur s’élève à des millions d’opérations pour chaque image.Techniques that operate on the full screen can be expensive since their order of magnitude is millions of operations every frame. Il est recommandé d’éviter les effets de post-traitement, comme l’anticrénelage, un écart des doigts paume vers le haut, etc.It's recommended to avoid post-processing effects such as anti-aliasing, bloom, and more.

Paramètres d’éclairage optimauxOptimal lighting settings

L’illumination globale en temps réel dans Unity peut donner des résultats visuels époustouflants, mais implique des calculs d’éclairage coûteux.Real-time Global Illumination in Unity can provide outstanding visual results but involves expensive lighting calculations. Il est recommandé de désactiver l’illumination globale en temps réel pour chaque fichier de scène Unity par le biais de Window > Rendering > Lighting Settings > Décochez Real-time Global Illumination.We recommended disabling real-time Global Illumination for every Unity scene file via Window > Rendering > Lighting Settings > Uncheck Real-time Global Illumination.

En outre, il est recommandé de désactiver la projection d’ombres, car elle ajoute également des passes de GPU coûteuses à une scène Unity.Furthermore, it's recommended to disable all shadow casting as these also add expensive GPU passes onto a Unity scene. Les ombres peuvent être désactivées par lumière, mais également contrôlées de façon holistique par le biais des paramètres de qualité.Shadows can be disable per light but can also be controlled holistically via Quality settings.

Sélectionnez Edit > Project Settings, puis la catégorie Quality et Low Quality pour la plateforme UWP.Edit > Project Settings, then select the Quality category > Select Low Quality for the UWP Platform. Vous pouvez également affecter simplement à la propriété Shadows la valeur Disable Shadows.One can also just set the Shadows property to Disable Shadows.

Nous vous recommandons d’utiliser l’éclairage baked avec vos modèles dans Unity.We recommended that you use baked lighting with your models in Unity.

Réduire le nombre de polygonesReduce poly count

Le nombre de polygones est réduit par les opérations suivantes :Polygon count is reduced by either

  1. Suppression d’objets dans une scèneRemoving objects from a scene
  2. Décimation des ressources qui réduit le nombre de polygones pour un maillage donnéAsset decimation, which reduces the number of polygons for a given mesh
  3. Implémentation d’un système de niveau de détail (LOD) dans votre application qui restitue des objets lointains avec une version polygonale moindre de la même géométrieImplementing a Level of Detail (LOD) System into your application, which renders far away objects with lower-polygon version of the same geometry

Présentation des nuanceurs dans UnityUnderstanding shaders in Unity

Une approximation facile pour comparer les performances des nuanceurs consiste à identifier le nombre moyen d’opérations que chacun exécute au moment de l’exécution.An easy approximation to compare shaders in performance is to identify the average number of operations each executes at runtime. Cette opération est simple dans Unity.This can be done easily in Unity.

  1. Sélectionnez votre ressource de nuanceur ou un matériau puis, dans le coin supérieur droit de la fenêtre de l’inspecteur, sélectionnez l’icône en forme d’engrenage, puis « Select Shader »Select your shader asset or select a material, then in the top-right corner of the inspector window, select the gear icon followed by "Select Shader"

    Select Shader dans Unity

  2. Une fois la ressource de nuanceur sélectionnée, sélectionnez le bouton « Compile and show code » sous la fenêtre de l’inspecteurWith the shader asset selected, select the "Compile and show code" button under the inspector window

    Compile Shader Code dans Unity

  3. Après la compilation, recherchez dans la section des statistiques des résultats le nombre d’opérations différentes pour le nuanceur de vertex et de pixels (remarque : les nuanceurs de pixels sont souvent également appelés nuanceurs de fragments).After compiling, look for the statistics section in the results with the number of different operations for both the vertex and pixel shader (Note: pixel shaders are often also called fragment shaders)

    Opérations des nuanceurs standard Unity

Optimiser les nuanceurs de pixelsOptimize pixel shaders

En examinant les résultats des statistiques compilés à l’aide de la méthode ci-dessus, le nuanceur de fragments exécute généralement plus d’opérations que le nuanceur de vertex, en moyenne.Looking at the compiled statistic results using the method above, the fragment shader will generally execute more operations than the vertex shader, on average. Le nuanceur de fragments, également connu sous le nom de nuanceur de pixels, est exécuté par pixel sur la sortie d’écran, tandis que le nuanceur de vertex est exécuté uniquement par vertex de tous les maillages dessinés à l’écran.The fragment shader, also known as the pixel shader, is executed per pixel on the screen output while the vertex shader is only executed per-vertex of all meshes being drawn to the screen.

Ainsi, non seulement les nuanceurs de fragments ont plus d’instructions que les nuanceurs de vertex en raison de tous les calculs d’éclairage, mais les nuanceurs de fragments sont aussi presque toujours exécutés sur un jeu de données plus volumineux.Thus, not only do fragment shaders have more instructions than vertex shaders because of all the lighting calculations, fragment shaders are almost always executed on a larger dataset. Par exemple, si la sortie d’écran est une image 2k par 2k, alors le nuanceur de fragments peut être exécuté 2 000 * 2 000 = 4 millions de fois.For example, if the screen output is a 2k by 2k image, then the fragment shader can get executed 2,000*2,000 = 4,000,000 times. En cas de rendu de deux yeux, ce nombre double puisqu’il y a deux écrans.If rendering two eyes, this number doubles since there are two screens. Si une application de réalité mixte a plusieurs passes, des effets de post-traitement plein écran ou un rendu de plusieurs maillages sur le même pixel, ce nombre augmente considérablement.If a mixed reality application has multiple passes, full-screen post-processing effects, or rendering multiple meshes to the same pixel, this number will increase dramatically.

Par conséquent, la réduction du nombre d’opérations dans le nuanceur de fragments peut entraîner des gains de performance bien supérieurs aux optimisations dans le nuanceur de vertex.Therefore, reducing the number of operations in the fragment shader can generally give far greater performance gains over optimizations in the vertex shader.

Alternatives aux nuanceurs standard UnityUnity Standard shader alternatives

Au lieu d’utiliser un rendu physique ou un autre nuanceur haute qualité, envisagez d’utiliser un nuanceur plus performant et moins onéreux.Instead of using a physically based rendering (PBR) or another high-quality shader, look at utilizing a more performant and cheaper shader. Mixed Reality Toolkit fournit le nuanceur standard MRTK optimisé pour les projets de réalité mixte.The Mixed Reality Toolkit provides the MRTK standard shader that has been optimized for mixed reality projects.

Unity fournit également des options de nuanceur simplifiées, comme l’absence d’éclairage, l’éclairage des vertex et la lumière diffuse, qui sont plus rapides par rapport au nuanceur Unity standard.Unity also provides an unlit, vertex lit, diffuse, and other simplified shader options that are faster compared to the Unity Standard shader. Pour plus d’informations, consultez Utilisation et performances des nuanceurs intégrés.See Usage and Performance of Built-in Shaders for more detailed information.

Préchargement des nuanceursShader preloading

Utilisez le préchargement des nuanceurs et d’autres astuces pour optimiser le temps de chargement des nuanceurs.Use Shader preloading and other tricks to optimize shader load time. Plus particulièrement, le préchargement des nuanceurs signifie que vous ne rencontrerez aucune anicroche en raison de la compilation des nuanceurs au moment de l’exécution.In particular, shader preloading means you won't see any hitches due to runtime shader compilation.

Limiter le surdessinLimit overdraw

Dans Unity, vous pouvez afficher le surdessin pour votre scène, en utilisant le menu du mode dessin dans le coin supérieur gauche de la vue de la scène et en sélectionnant Overdraw.In Unity, one can display overdraw for their scene, by toggling the draw mode menu in the top-left corner of the Scene view and selecting Overdraw.

En règle générale, le surdessin peut être atténué en éliminant les objets à l’avance avant leur envoi au GPU.Generally, overdraw can be mitigated by culling objects ahead of time before they're sent to the GPU. Unity fournit des détails sur l’implémentation de l’élimination des occlusions pour son moteur.Unity provides details on implementing Occlusion Culling for their engine.

Recommandations sur la mémoireMemory recommendations

Les opérations d’allocation et de désallocation de mémoire excessives peuvent avoir des effets négatifs sur votre application holographique, entraînant des performances irrégulières, des frames figées et d’autres comportements néfastes.Excessive memory allocation & deallocation operations can have adverse effects on your holographic application, resulting in inconsistent performance, frozen frames, and other detrimental behavior. Il est particulièrement important de bien comprendre les considérations relatives à la mémoire pour développer dans Unity, car la gestion de la mémoire est contrôlée par le garbage collector.It's especially important to understand memory considerations when developing in Unity since memory management is controlled by the garbage collector.

Nettoyage de la mémoireGarbage collection

Les applications holographiques perdent du temps de calcul de traitement dans le garbage collector (GC) quand le GC est activé pour analyser des objets qui ne sont plus dans la portée pendant l’exécution et quand leur mémoire doit être libérée, de sorte à être rendue disponible à des fins de réutilisation.Holographic apps will lose processing compute time to the garbage collector (GC) when the GC is activated to analyze objects that are no longer in scope during execution and their memory needs to be released, so it can be made available for reuse. Les allocations et désallocations constantes nécessitent généralement que le garbage collector s’exécute plus fréquemment, ce qui nuit aux performances et à l’expérience utilisateur.Constant allocations and de-allocations will generally require the garbage collector to run more frequently, thus hurting performance and user experience.

Unity propose une excellente page qui explique précisément comment le garbage collector fonctionne et donne des conseils pour écrire du code plus efficace en termes de gestion de la mémoire.Unity has provided an excellent page that explains in detail how the garbage collector works and tips to write more efficient code in regards to memory management.

L’une des pratiques les plus courantes qui conduisent à un nettoyage de la mémoire excessif consiste à ne pas mettre en cache les références aux composants et aux classes dans le développement Unity.One of the most common practices that leads to excessive garbage collection isn't caching references to components and classes in Unity development. Toutes les références doivent être capturées pendant Start() ou Awake() et réutilisées dans des fonctions ultérieures comme Update() ou LateUpdate().Any references should be captured during Start() or Awake() and reused in later functions such as Update() or LateUpdate().

Autres conseils rapides :Other quick tips:

  • Utilisez la classe C# StringBuilder pour créer dynamiquement des chaînes complexes au moment de l’exécution.Use the StringBuilder C# class to dynamically build complex strings at runtime
  • Supprimez les appels à Debug.log() quand vous n’en avez plus besoin, car ils s’exécutent encore dans toutes les versions de build d’une application.Remove calls to Debug.Log() when no longer needed, as they still execute in all build versions of an app
  • Si votre application holographique nécessite généralement beaucoup de mémoire, envisagez d’appeler System.GC.Collect() pendant les phases de chargement, par exemple lors de la présentation d’un écran de chargement ou de transition.If your holographic app generally requires lots of memory, consider calling System.GC.Collect() during loading phases such as when presenting a loading or transition screen

Mise en pool d’objetsObject pooling

Le mise en pool d’objets est une technique connue pour réduire le coût des allocations et désallocations continues d’objets.Object pooling is a popular technique for reducing the cost of continuous object allocation and deallocations. Pour la réaliser, vous devez allouer un grand pool d’objets identiques et réutiliser des instances inactives disponibles de ce pool au lieu de générer et détruire constamment des objets au fil du temps.This is done by allocating a large pool of identical objects and reusing inactive, available instances from this pool instead of constantly spawning and destroying objects over time. Les pools d’objets conviennent parfaitement aux composants réutilisables qui ont une durée de vie variable pendant une application.Object pools are great for reuseable components that have variable lifetime during an app.

Performances de démarrageStartup performance

Envisagez de démarrer votre application avec une scène plus petite, puis d’utiliser SceneManager.LoadSceneAsync pour charger le reste de la scène.Consider starting your app with a smaller scene, then using SceneManager.LoadSceneAsync to load the rest of the scene. Cela permet à votre application d’accéder à un état interactif aussi rapidement que possible.This allows your app to get to an interactive state as fast as possible. Il peut y avoir un pic de consommation de processeur important pendant l’activation de la nouvelle scène et que tout contenu rendu peut être saccadé ou figé.There may be a large CPU spike while the new scene is being activated and that any rendered content might stutter or hitch. Pour contourner ce problème, vous pouvez affecter à la propriété AsyncOperation.allowSceneActivation la valeur « false » sur la scène en cours de chargement, attendre que la scène se charge, effacer l’écran trop noir, puis affecter la valeur « true » pour terminer l’activation de la scène.One way to work around this is to set the AsyncOperation.allowSceneActivation property to "false" on the scene being loaded, wait for the scene to load, clear the screen too black, and then set it back to "true" to complete the scene activation.

N’oubliez pas que pendant le chargement de la scène de démarrage, l’écran de démarrage holographique est présenté à l’utilisateur.Remember that while the startup scene is loading, the holographic splash screen will be displayed to the user.

Voir aussiSee also