
Ceci est le cinquième d'une série d'articles qui déploie des conseils d'optimisation pour vos projets Unity. Utilisez-les comme guide pour fonctionner à des taux d'images 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 :
La physique peut créer un gameplay complexe, mais cela a un coût en performances. Une fois que vous connaissez ces coûts, vous pouvez ajuster la simulation pour les gérer correctement. Utilisez ces conseils pour rester dans votre taux d'images cible et créer une lecture fluide avec la physique intégrée de Unity (NVIDIA PhysX).
Consultez nos derniers guides d'optimisation pour les développeurs et artistes Unity 6 :
Les maillages utilisés dans la physique passent par un processus appelé cuisson. Cela prépare le maillage afin qu'il puisse fonctionner avec des requêtes physiques comme les raycasts, les contacts, etc.
Un MeshCollider a plusieurs OptionsDeCuisson pour vous aider à valider le maillage pour la physique. Si vous êtes certain que votre maillage n'a pas besoin de ces vérifications, vous pouvez les désactiver pour accélérer votre temps de cuisson.
Dans les OptionsDeCuisson pour chaque MeshCollider, il suffit de décocher EnableMeshCleaning, WeldColocatedVertices et CookForFasterSimulation. Ces options sont précieuses pour les maillages générés procéduralement à l'exécution, mais peuvent être désactivées si vos maillages ont déjà les bons triangles.
De plus, si vous ciblez PC, assurez-vous de garder Use Fast Midphase activé. Cela passe à un algorithme plus rapide de PhysX 4.1 pendant la phase intermédiaire de la simulation (ce qui aide à réduire un petit ensemble de triangles potentiellement intersectants pour les requêtes physiques).
En savoir plus dans la documentation des OptionsDeCuisson.

Si vous générez des maillages de manière procédurale pendant le gameplay, vous pouvez créer un Mesh Collider à l'exécution. Ajouter un composant MeshCollider directement au maillage, cependant, cuit/fait cuire la physique sur le thread principal. Cela peut consommer un temps CPU significatif.
Utilisez Physics.BakeMesh pour préparer un maillage à utiliser avec un MeshCollider et enregistrez les données cuites avec le maillage lui-même. Un nouveau MeshCollider référencant ce maillage réutilisera ces données pré-cuites (plutôt que de cuire à nouveau le maillage). Cela peut aider à réduire le temps de chargement de la scène ou le temps d'instanciation par la suite.
Pour optimiser les performances, vous pouvez décharger la cuisson du maillage sur un autre thread avec le C# job system.
Référez-vous à cet exemple pour des détails sur la cuisson des maillages à travers plusieurs threads.

Dans les Paramètres Joueur, cochez Pré-cuire les maillages de collision chaque fois que possible. Nous recommandons également de revoir la configuration de la Matrice de Collision pour s'assurer que les objets du joueur et de la mécanique de jeu sont dans les bonnes couches.
Supprimer les rappels des déclencheurs pour des couches inutiles peut être un grand avantage, alors essayez de simplifier votre Matrice de Collision des Couches. Vous pouvez modifier vos Paramètres de Physique via Paramètres du Projet > Physique.
En savoir plus dans la documentation de la Matrice de Collision.

Les moteurs de physique fonctionnent en exécutant un pas de temps fixe. Pour voir le taux fixe auquel votre projet fonctionne, allez à Modifier > Paramètres du Projet > Temps.
Le champ Fixed Timestep définit le delta de temps utilisé par chaque étape de physique. Par exemple, la valeur par défaut de 0,02 secondes (20 ms) équivaut à 50 fps, ou 50 Hz.
Parce que chaque image dans Unity prend un temps variable, elle n'est pas parfaitement synchronisée avec la simulation physique. Le moteur compte jusqu'à la prochaine étape de temps physique. Si un cadre s'exécute légèrement plus lentement ou plus rapidement, Unity utilise le temps écoulé pour savoir quand exécuter la simulation physique au bon pas de temps.
Dans le cas où un cadre prend beaucoup de temps à se préparer, cela peut entraîner des problèmes de performance. Par exemple, si votre jeu connaît un pic (par exemple, instancier de nombreux GameObjects ou charger un fichier depuis le disque), le cadre pourrait prendre 40 ms ou plus à s'exécuter. Avec le pas de temps fixe par défaut de 20 ms, cela entraînerait deux simulations physiques à s'exécuter sur le cadre suivant afin de "rattraper" le pas de temps variable.
Des simulations physiques supplémentaires, à leur tour, ajoutent plus de temps pour traiter le cadre. Sur les plateformes de bas de gamme, cela peut potentiellement entraîner une spirale descendante de performance.
Un cadre suivant prenant plus de temps à se préparer rend également l'arriéré de simulations physiques plus long. Cela conduit à des cadres encore plus lents et encore plus de simulations à exécuter par cadre. Le résultat est une performance de plus en plus mauvaise.
Finalement, le temps entre les mises à jour physiques pourrait dépasser le pas de temps maximum autorisé. Après cette coupure, Unity commence à ignorer les mises à jour physiques, et le jeu saccade.
Pour éviter les problèmes de performance avec la physique :
Simulez le pas de physique manuellement si nécessaire en choisissant le ModeSimulation pendant la phase de mise à jour du cadre. Cela vous permet de prendre le contrôle du moment où exécuter l'étape de physique. Passez Time.deltaTime à Physics.Simulate afin de garder la physique synchronisée avec le temps de simulation. Cette approche peut provoquer des instabilités dans la simulation physique dans des scènes avec une physique complexe ou des temps de trame très variables, donc utilisez-la avec prudence.
En savoir plus dans la documentation de Physics.Simulate.

Le moteur physique Unity fonctionne en deux étapes :
Le paramètre par défaut de la broad phase de Sweep and Prune BroadPhase (Edit > Paramètres du projet > Physique > Type de broad-phase) peut générer des faux positifs pour des mondes qui sont généralement plats et ont de nombreux colliders. Si votre scène est grande et principalement plate, évitez ce problème et passez à Automatic Box Pruning ou Multibox Pruning Broadphase. Ces options divisent le monde en une grille, où chaque cellule de la grille effectue un sweep-and-prune.
Multibox Pruning Broadphase vous permet de spécifier manuellement les limites du monde et le nombre de cellules de la grille, tandis que Automatic Box Pruning calcule cela pour vous.
Voir la liste complète des propriétés de physique ici.

Si vous souhaitez simuler un corps physique spécifique plus précisément, augmentez ses Rigidbody.solverIterations.
Cela remplace les Physics.defaultSolverIterations, qui peuvent également être trouvés dans Edit > Paramètres du projet > Physique > Itérations de solveur par défaut.
Pour optimiser vos simulations physiques, définissez une valeur relativement basse dans les defaultSolveIterations du projet. Appliquez ensuite des valeurs plus élevées de Rigidbody.solverIterations aux instances individuelles qui nécessitent plus de détails.
Obtenez plus d'informations sur Rigidbody.solverIterations.

Par défaut, Unity ne synchronise pas automatiquement les modifications des Transforms avec le moteur physique. Au lieu de cela, il attend la prochaine mise à jour physique ou jusqu'à ce que vous appeliez manuellement Physics.SyncTransforms. Lorsque cela est activé, tout Rigidbody ou Collider sur ce Transform ou ses enfants se synchronise automatiquement avec le moteur physique.
Quand synchroniser manuellement
Lorsque autoSyncTransforms est désactivé, Unity ne synchronise les transformations qu'avant l'étape de simulation physique dans FixedUpdate ou lorsqu'il est explicitement demandé via Physics.Simulate. Vous pourriez avoir besoin d'effectuer des synchronisations supplémentaires si vous utilisez des API qui lisent directement à partir du moteur physique entre les changements de Transform et la mise à jour physique. Les exemples incluent l'accès à Rigidbody.position ou l'exécution de Physics.Raycast.
Meilleure pratique de performance
Bien que autoSyncTransforms garantisse des requêtes physiques à jour, cela entraîne un coût de performance. Chaque appel d'API lié à la physique force une synchronisation, ce qui peut dégrader les performances, surtout avec plusieurs requêtes successives. Suivez ces meilleures pratiques :
Découvrez-en plus sur Physics.SyncTransforms.

Les tableaux de contacts sont généralement significativement plus rapides et donc la recommandation générale est d'utiliser ceux-ci plutôt que de réutiliser les rappels de collision, cependant, considérez ce qui suit si vous avez un cas d'utilisation spécifique pour cela.
Les rappels MonoBehaviour.OnCollisionEnter, MonoBehaviour.OnCollisionStay et MonoBehaviour.OnCollisionExit prennent tous une instance de collision comme paramètre. Cette instance de collision est allouée sur le tas géré et doit être collectée par le ramasse-miettes.
Pour réduire la quantité de déchets générés, activez Physics.reuseCollisionCallbacks (également trouvé dans Projects Settings > Physics > Reuse Collision Callbacks). Avec cela actif, Unity n'assigne qu'une seule instance de paire de collision à chaque rappel. Cela réduit le gaspillage pour le ramasse-miettes et améliore les performances.
La recommandation générale est d'activer toujours Reuse Collision Callbacks pour des avantages de performance. Vous ne devriez désactiver cette fonctionnalité que pour les projets hérités où le code dépend d'instances individuelles de la classe Collision, rendant impraticable le stockage de champs individuels.
En savoir plus sur Physics.reuseCollisionCallbacks.

Les colliders statiques sont des GameObjects avec un composant Collider mais sans Rigidbody.
Notez que vous pouvez déplacer un collider statique, contrairement au terme "statique". Pour ce faire, modifiez simplement la position du corps physique. Accumulez les changements de position et synchronisez avant la mise à jour physique. Vous n'avez pas besoin d'ajouter un composant Rigidbody au collider statique juste pour le déplacer.
Cependant, si vous souhaitez que le collider statique interagisse avec d'autres corps physiques de manière plus complexe, donnez-lui un kinematic Rigidbody. Utilisez Rigidbody.position et Rigidbody.rotation pour le déplacer au lieu d'accéder au composant Transform. Cela garantit un comportement plus prévisible du moteur physique.
Remarque : Si un Collider 2D statique individuel doit être déplacé ou reconfiguré à l'exécution, ajoutez un composant Rigidbody 2D et définissez-le sur le type de corps Static, car il est plus rapide de simuler le Collider 2D lorsqu'il a son propre Rigidbody 2D. Si un groupe de Collider 2Ds doit être déplacé ou reconfiguré à l'exécution, il est plus rapide de les avoir tous comme enfants du Rigidbody 2D parent caché unique que de déplacer chaque GameObject individuellement.
Obtenez plus d'informations sur Rigidbodies.
Pour détecter et collecter des colliders dans des projets 3D dans une certaine distance et dans une certaine direction, utilisez des raycasts et d'autres requêtes physiques comme BoxCast. Notez que
Les requêtes de physique qui renvoient plusieurs colliders sous forme de tableau, comme OverlapSphere ou OverlapBox, doivent allouer ces objets sur le tas géré. Cela signifie que le ramasse-miettes doit finalement collecter les objets alloués, ce qui peut diminuer les performances si cela se produit au mauvais moment.
Pour réduire cette surcharge, utilisez les versions NonAlloc de ces requêtes. Par exemple, si vous utilisez OverlapSphere pour collecter tous les colliders potentiels autour d'un point, utilisez OverlapSphereNonAlloc à la place.
Cela vous permet de passer un tableau de colliders (le paramètre des résultats) pour agir comme un tampon. La méthode NonAlloc fonctionne sans générer de déchets. Sinon, elle fonctionne comme la méthode d'allocation correspondante.
Notez que vous devez définir un tampon de résultats de taille suffisante lorsque vous utilisez une méthode NonAlloc. Le tampon ne grandit pas s'il manque d'espace.
Physique de la 2D
Notez que les conseils ci-dessus ne s'appliquent pas aux requêtes de physique 2D, car dans le système de physique 2D de Unity, les méthodes n'ont pas de suffixe "NonAlloc". Au lieu de cela, toutes les méthodes de physique 2D, y compris celles qui renvoient plusieurs résultats, fournissent des surcharges qui acceptent des tableaux ou des listes. Par exemple, alors que le système de physique 3D a des méthodes comme RaycastNonAlloc, l'équivalent 2D utilise simplement une version surchargée de Raycast qui peut prendre un tableau ou List comme paramètre, tel que :
var results = new List();
int hitCount = Physics2D.Raycast(origin, direction, contactFilter, results);
En utilisant des surcharges, vous pouvez effectuer des requêtes non allouées dans le système de physique 2D sans avoir besoin de méthodes NonAlloc spécialisées.
En savoir plus dans la documentation de la méthode NonAlloc.
Vous pouvez exécuter des requêtes de raycast avec Physics.Raycast. Cependant, si vous avez un grand nombre d'opérations de raycast (par exemple, calculer la ligne de vue pour 10 000 agents), cela peut prendre une quantité significative de temps CPU.
Utilisez RaycastCommand pour regrouper la requête en utilisant le système de tâches C#. Cela décharge le travail du thread principal afin que les raycasts puissent se produire de manière asynchrone et en parallèle.
Voir un exemple dans la documentation des RaycastCommands.
Utilisez la fenêtre de débogage physique (Fenêtre > Analyse > Débogueur physique) pour aider à résoudre tout problème de colliders ou de divergences. Cela montre un indicateur codé par couleur des GameObjects qui peuvent entrer en collision les uns avec les autres.
Pour plus d'informations, voir la documentation du débogueur physique.


Trouvez plus de meilleures pratiques et conseils dans le centre des meilleures pratiques Unity. Choisissez parmi plus de 30 guides, créés par des experts de l'industrie, ainsi que par des ingénieurs et artistes techniques de Unity, qui vous aideront à développer efficacement avec les outils et systèmes de Unity.