De nombreux jeux utilisent des moteurs physiques pour piloter la façon dont les choses bougent et réagissent. L'utilisation d'un moteur physique peut ajouter l'immersion, la gloire à l'oeil et, mieux encore, un gameplay émergent, mais peut également, si elle est utilisée incorrectement, conduire à des résultats irréalistes ou à des problèmes de mise au point. Dans cet article, j'expliquerai comment identifier et résoudre les problèmes courants rencontrés dans les jeux d'aujourd'hui..
Nous allons examiner et résoudre ces problèmes comme dans Unity, en nous concentrant sur le moteur de physique 3D intégré, Nvidia PhysX, mais les principes fondamentaux peuvent être appliqués à toute autre plate-forme et moteur de physique..
Remarque: vous pouvez trouver une large sélection de modèles 3D pour vous aider à démarrer sur le marché Envato..
Cette démo montre que la plupart des erreurs mentionnées dans cet article sont à la fois dans un état incorrect ou cassé et dans un état fixe:
Ceci est une scène simple avec une balle qui frappe une pile de barils. La version alternative Echelle incorrecte (10x) montre comment la scène change à l'échelle 10x (voir les marquages d'échelle sur le sol de la démo). Notez comme il semble être au ralenti, mais cet effet est simplement causé par la taille de la scène.
Cela montre un simple jeu de défilement horizontal fonctionnant comme prévu. La "mauvaise" alternative; Rigidbody & Character Controller Ensemble montre le même jeu, mais avec un composant Rigidbody attaché au personnage. Remarquez comment le Rigidbody rompt le comportement du contrôleur de personnage.
Les tonneaux sont tirés du côté de la scène et sont lancés dans les airs. Alors qu'ils s'effondrent, ils rebondissent et se déplacent de façon simple mais majestueuse. La version cassée montre la même scène sans faste, et elle est tellement plus ennuyeuse en comparaison.
Dans ce scénario, une balle lourde est poussée sur une rampe en utilisant Rigidbody.AddForce ()
. Dans le second scénario, au lieu d'utiliser Rigidbody.AddForce ()
déplacer la balle sur la rampe, Transform.position
est utilisé. Le résultat de l'utilisation Transform.position
est que la balle redescend, en raison du fait que le corps rigide ne prend pas correctement en compte le changement de vitesse du corps rigide, mais ensuite, la modification de la position provoque la balle à la gigue de haut en bas de la rampe.
Dans la plupart des jeux, les joueurs présument que l’échelle du monde est comparable à celle de la Terre. Ils s'attendent, par exemple, à ce qu'un ennemi qui tombe d'une tour de guet tombe au même rythme que celui que vous percevriez sur Terre. Si l'ennemi tombe trop lentement ou trop rapidement, cela peut nuire à l'immersion, surtout s'il est à taille humaine.!
Nvidia PhysX dans Unity est configuré pour utiliser une unité par mètre. Vous pouvez utiliser cet attribut pour vérifier si l'échelle de vos objets est correcte en ajoutant simplement un cube primitif Unity. Le cube primitif est exactement un mètre cube. Si vous remarquez, par exemple, qu’un baril de pétrole dans votre scène est deux fois plus gros que le cube, cela signifie que votre baril de pétrole mesure deux mètres de haut (6,56 pieds).!
La fixation de l'échelle est aussi simple que la mise à l'échelle de chaque objet de la scène. Il suffit de sélectionner tous les objets de votre scène et d'utiliser le Échelle outil pour les rendre plus gros ou plus petit. Si vous remarquez que vos objets se déplacent trop rapidement, agrandissez-les. Si vous remarquez le contraire, à savoir que les objets bougent trop lentement, vous devez les réduire..
Vous pouvez redimensionner vos objets avec plus de précision en les regroupant dans un seul objet null et en le redimensionnant. Par exemple, en définissant l’échelle de l’objet parent sur 1.2
sur chaque axe, la taille de chaque objet de l'objet augmente de 20%. Vous pouvez également redimensionner les objets par incréments à l'aide de l'outil Mise à l'échelle en maintenant enfoncée la touche Ctrl-LMB (Windows) ou Cmd-LMB (OS X).
J'ai vu cela se produire plusieurs fois et il est logique que cela se produise souvent. Le développeur suppose qu'un contrôleur de personnage est nécessaire pour contrôler son avatar, mais il souhaite que l'avatar soit affecté par la gravité et d'autres objets de l'environnement..
Le problème est que Contrôleur de personnage est conçu pour des contrôles plus classiques, comme ceux que l'on trouve généralement dans un jeu de plateforme ou un jeu de tir à la première personne. UNE Corps rigide est simplement un objet indéformable qui est affecté par la gravité et d’autres forces physiques (telles que la collision d’autres objets). Ce sont deux composants très distincts, avec des utilisations prévues différentes.
Choisissez uniquement un contrôleur de personnage lorsque vous souhaitez avoir le contrôle complet du déplacement du joueur. D'autre part, si vous voulez que votre personnage soit entraîné par le moteur physique, utilisez un Rigidbody. En ajoutant un Rigidbody à un personnage, vous voudrez probablement limiter la rotation afin que le joueur ne bascule pas.
Contrairement à un contrôleur de personnage, il n'est pas conseillé de définir la position ou la rotation d'un corps rigide, ou de redimensionner constamment un objet de corps rigide (pour le contrôle du joueur, etc.). Au lieu de cela, vous devez utiliser les méthodes AddForce () et AddTorque () trouvées dans la classe Rigidbody. Vous pouvez définir directement la position et la rotation d'un Rigidbody si, par exemple, vous créez l'objet pour la première fois ou si vous réinitialisez la scène. Dans cette situation, tout ira bien tant que le Rigidbody ne croise pas d’autres objets.
Cela est important car, lorsqu'un corps rigide est déplacé dans une position exacte ou dans un état de rotation, il peut passer à travers un objet. Le moteur physique doit alors corriger ce problème et, la plupart du temps, il ne tourne pas en même temps. Mettre à jour()
le message fait. Le résultat final est un comportement instable à chaque intersection, et il est possible que le corps rigide passe entièrement à travers des objets..
Un autre effet secondaire néfaste qui peut se produire lorsque, par exemple, le déplacement d’un corps rigide le long d’un axe de déplacement du joueur est que le corps rigide est simulé en interne et qu’il applique ensuite sa position. La mise à jour de la position déplace alors le corps rigide sans prendre en compte le changement de vitesse, etc. Si le corps rigide redescend une pente, il reculera le corps rigide pendant que votre code de modification de position le fera remonter dans la pente..
Disons que vous développez un jeu de golf. Il y a un problème avec le fait que la balle de golf n'arrête pas de rouler et parvient d'une manière ou d'une autre à continuer à rouler éternellement tant qu'il n'y a aucun type de trou ou de fossé sur son chemin. La raison en est que, dans la réalité, le ballon serait ralenti par l'herbe sur laquelle il roulerait (entre autres choses), car il devait pousser les minuscules brins d'herbe vers le bas, l'herbe ressemblant essentiellement à une rampe constante. C'est appelé résistance au roulement. Unity ne peut pas simuler ce comportement avec précision. Il faut donc utiliser des forces d'arrêt artificielles..
Dans Unity, la meilleure force à utiliser pour empêcher un objet de rouler à jamais est la "traînée angulaire". Changer la traînée angulaire de la balle de golf est le moyen de résoudre ce problème. La valeur exacte dépend vraiment du comportement que vous recherchez. Cependant, vous remarquerez peut-être qu'une valeur de traînée angulaire de 1.0 peut même ne pas être suffisante dans certains cas..
Presque tous les objets du monde rebondissent après un impact. Le matériel de physique interne par défaut de Unity n'a pas de rebond. Cela signifie que chaque objet ne rebondira pas sauf si vous remplacez le matériau physique par défaut ou appliquez un matériau physique aux objets de votre scène avec une valeur de dépassement supérieure à 0..
L’un des meilleurs moyens de résoudre ce problème consiste à créer votre propre matériel de physique par défaut et à l’affecter à Responsable Physique trouvé en cliquant Édition> Paramètres du projet> Physique.
La plupart des moteurs physiques ont une sorte de paramètre dictant le degré d'interpénétration ou d'intersection de deux objets jusqu'à ce qu'ils soient éloignés l'un de l'autre. Ce paramètre s'appelle Pénétration min. Pour pénalité en unité. Par défaut, cette valeur est 0,01 (mètres), ce qui signifie que, par défaut, les objets peuvent se croiser jusqu'à 1 centimètre (presque 0,4 pouce) avant d'être écartés..
Vous devriez définir Min Penetration For Penalty à une valeur où il est à peine perceptible que les objets se croisent. Définir la valeur sur quelque chose de petit, tel que 0,0001
, peut entraîner des corps rigides instables.
Si vous n'êtes pas un programmeur, vous n'avez pas à vous soucier du scénario suivant. Lorsque vous écrivez du code qui déplace, fait pivoter ou met à l'échelle des corps rigides, il est important de le conserver dans la boucle FixedUpdate. Écrire ce code dans le Mettre à jour
boucle entraînera potentiellement des résultats instables, car la Mettre à jour
fonction peut être appelée à 1000 Hz, alors que le moteur physique et le FixedUpdate
les fonctions sont appelées chacune à 50 Hz par défaut.
Vous pouvez changer la fréquence sur les étapes de la physique en changeant le paramètre Horodatage fixe, trouvé dans Édition> Paramètres du projet> Heure. La valeur détermine combien de temps est attendu, en secondes, entre chaque mise à jour physique ou étape. Vous pouvez calculer la fréquence en Hertz en divisant 1 par la valeur (par exemple, une attente de 0,01 seconde signifie 1 / 0,01 = 100 Hz). Plus les étapes sont fréquentes, plus la simulation sera précise et stable. Cependant, si vous fixez une fréquence supérieure à celle que le processeur peut gérer, la simulation sera très instable. Essayez de garder la fréquence de mise à jour fixe entre 30 Hz et 100 Hz.
Alors que je travaillais sur un mur de briques destructible, je suis tombé sur un problème causé par l’instanciation de briques après la destruction d’une partie du mur. J'ai résolu ce problème en plaçant le code problématique dans une Coroutine et en plaçant la ligne suivante avant de détruire l'objet:
// Attendre un retour d'image nul; // rendement C #; // UnityScript
En attendant un cadre, cela garantissait que la logique était synchronisée dans Heure de mise à jour, plutôt que dans Heure mise à jour. Cela semble vouloir dire que la fonction Destroy est exécutée en synchronisation avec la boucle Update..
Le paquet Physics Materials, qui fait partie des actifs standard d'Unity, est en réalité presque totalement inutile. Le paquet contient cinq matériaux de physique, et tous sont irréalistes d’une manière ou d’une autre.
Chaque matériau présente des frottements statiques et dynamiques identiques. Dans le monde réel, les objets qui se tiennent immobiles ont légèrement plus de friction que lorsqu'ils se déplacent. Le coefficient de frottement du caoutchouc est 1,0
, qui ne ressemble à aucun caoutchouc dans le monde réel. Et si cela ne semble pas assez idiot, chaque matériau a 0 "rebondissement" (à l’exception du matériau "Bouncy"). Tout cela signifie que les matériaux ne représentent même pas fidèlement leur contrepartie réelle.
Il est préférable de créer vos propres matériaux de physique lorsque cela est nécessaire. Il existe de nombreux sites Web partageant les propriétés physiques des matériaux, les plus importants étant le frottement dynamique, le frottement statique et la restitution.
Très peu de problèmes liés à la physique sont aussi difficiles à résoudre. Si un bug lié à la physique vous semble difficile à détecter, essayez de ralentir le temps pour voir ce qui se passe. Si vous remarquez que le problème commence autour d'une certaine ligne de code, vous pouvez utiliser Debug.Break pour suspendre l'éditeur et inspecter ce qui se passe. N'hésitez pas à commenter ici si vous avez des questions ou avez besoin d'aide.