L'événement On collision de Unity vous donne un objet Collision qui vous donne des informations sur la collision qui s'est produite (y compris une liste de ContactPoints avec des normales de hit).
Mais ce que vous n'obtenez pas, ce sont des normales de surface pour le collisionneur que vous frappez. Voici une capture d'écran pour illustrer. La ligne rouge est de ContactPoint.normal
et la ligne bleue est de RaycastHit.normal
.
Est-ce une instance de Unity cachant des informations pour fournir une API simplifiée? Ou les techniques de détection de collision 3D en temps réel ne collectent-elles tout simplement pas ces informations?
Et pour la deuxième partie de la question, quel est un moyen infaillible et relativement efficace d'obtenir une surface normale pour une collision?
Je sais que le raycasting vous donne des normales de surface, mais il semble que je doive faire plusieurs raycasts pour accomplir cela pour tous les scénarios (peut-être qu'un point de contact / une combinaison normale manque le collisionneur sur la première distribution, ou peut-être que vous devez faire une moyenne de tous les normales des points de contact pour obtenir le meilleur résultat).
Ma méthode actuelle:
Sauvegarder le
Collision.contacts[0].point
long de son hit normalRaycast sur le coup négatif normal pour
float.MaxValue
, leCollision.collider
Si cela échoue, répétez les étapes 1 et 2 avec la normale non inversée
Si cela échoue, essayez les étapes 1 à 3 avec
Collision.contacts[1]
Répétez 4 jusqu'à la réussite ou jusqu'à ce que tous les points de contact soient épuisés.
Abandonnez, revenez
Vector3.zero
.
Cela semble tout comprendre, mais tous ces raycasts me rendent mal à l'aise, et je ne sais pas comment tester que cela fonctionne pour suffisamment de cas. Y a-t-il une meilleure façon?
EDIT S'il s'agit vraiment de la façon dont les choses se passent avec les collisions 3D, un aperçu des raisons pour lesquelles dans le cas général serait tout aussi bienvenu que quelque chose de spécifique à Unity.
la source
Réponses:
C'est vraiment comme ça que les choses se passent avec les collisions. Pas seulement en 3D, mais aussi en 2D. Prenons l'exemple suivant:
Les AABB vert et rouge entrent en collision, et le collecteur de contact est la zone bleue. Les points de contact seront dans la zone bleue quelque part (exactement où peut varier selon l'algorithme, mais les coins où le bleu / rouge / vert se rencontrent sont idéaux).
Quelle surface normale doit être retournée? Le bord supérieur de l'AABB rouge ou le bord gauche? Si la boîte verte tombe, nous pouvons peut-être raisonnablement deviner le bord supérieur. s'il se déplace vers la droite, nous pouvons peut-être raisonnablement deviner le bord gauche. Et s'il se déplaçait vers le bas et à droite? Prenons-nous l'axe de moindre pénétration? L'axe de vitesse de la plus grande vitesse? Une heuristique des deux? Et si les boîtes étaient entrées en collision exactement dans les coins?
Étendez ceci à une surface 3D complexe potentiellement composée de 100s de tris / faces. Vous n'aurez toujours qu'un petit nombre de points de contact idéaux. Quelle surface normale doit être retournée? La surface moyenne normale sur l'ensemble du tri-mesh (ce qui n'a pas de sens pour la plupart des objets)? Les points directement "sous" les coins de la boîte en collision (qui ne sont pas bien définis pour la plupart des autres formes)? Essayez-vous de trouver la face la plus proche des points de contact générés (ce qui nécessiterait un deuxième passage, car les points de contact ne sont calculés directement à partir d'aucune face maillée)? Si vous trouvez la face la plus proche, prenez-vous la normale de la face ou interpolez-vous les sommets de la face au point de contact pour obtenir la normale correcte pour les objets "lisses"?
Vraiment, le principal problème est que les points de contact ne sont pas tous les points de contact. Dans de nombreux cas, ce serait un ensemble infini de points, après tout. Ce ne sont que quelques points bien répartis qui rendent raisonnablement possible l'approximation de la réaction physique en appliquant des forces auxdits points pour pousser les objets en collision de manière réaslitique. Les points / emplacements spécifiques du contact réel avec l'objet sont résumés derrière un modèle mathématique simplifié. Par conséquent, l'idée d'une surface spécifique normale de contact n'a tout simplement pas beaucoup de sens dans le cas général.
Bien sûr, avec des contraintes et des limitations plus spécifiques sur vos objets, le monde et le mouvement, vous pouvez créer des algorithmes de collision alternatifs qui peuvent vous renseigner sur la normale de la surface. Dans le cas 2D ci-dessus, si nous supposons que les boîtes ne tournent jamais et que nous connaissons la vitesse relative et la dernière position de chacune, nous pourrions utiliser la détection de collision continue pour savoir exactement quand elles entreraient en collision et quelles caractéristiques sont entrées en collision, ce qui nous fournirait la caractéristique exacte où la collision s'est produite, qui pourrait ensuite être utilisée comme normale de contact / collision / surface. Les jeux de plateforme sont entièrement construits sur de telles hypothèses et astuces spéciales (c'est pourquoi l'utilisation d'une bibliothèque de physique générale comme Box2D ou Havok ou la lumière ne produit jamais le genre de contrôle serré et précis que vous trouvez dans les plateformes classiques comme Mario ou Sonic; je ne le ferais pas veux le dire '
Les bibliothèques de physique newtonienne générale, comme celle utilisée dans Unity3D, ne peuvent pas faire ce genre de simplifications et d'hypothèses. Par conséquent, vous n'obtenez pas de normales de surface de collision, vous obtenez un collecteur de contacts, généralement simplifié jusqu'aux points de contact, et c'est tout.
la source