Pourquoi OnCollisionEnter d'Unity ne me donne-t-il pas des normales de surface, et quel est le moyen le plus fiable de les obtenir?

11

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.normalet la ligne bleue est de RaycastHit.normal.

entrez la description de l'image ici

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:

  1. Sauvegarder le Collision.contacts[0].pointlong de son hit normal

  2. Raycast sur le coup négatif normal pour float.MaxValue, leCollision.collider

  3. Si cela échoue, répétez les étapes 1 et 2 avec la normale non inversée

  4. Si cela échoue, essayez les étapes 1 à 3 avec Collision.contacts[1]

  5. Répétez 4 jusqu'à la réussite ou jusqu'à ce que tous les points de contact soient épuisés.

  6. 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.

michael.bartnett
la source
Est-ce juste par curiosité, ou essayez-vous de faire quelque chose et de rester coincé? Autrement dit, pourquoi pensez-vous que vous avez besoin de la surface normale? Posez une question sur l'effet que vous essayez d'obtenir, plutôt que sur la façon de «résoudre» une solution à un problème non spécifié, et quelqu'un pourrait être en mesure de vous aider à le résoudre. :)
Sean Middleditch
@SeanMiddleditch Je ne suis pas d'accord. La question est bien posée et c'est exactement ce que je cherchais. Cette question et ses réponses m'ont aidé à corriger certaines choses que je faisais mal.
SteakOverflow

Réponses:

12

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:

Chevauchement des AABB

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.

Sean Middleditch
la source
Ceci est une réponse fantastique, et exactement ce que je cherchais, merci. Le problème spécifique était d'obtenir un vecteur de réflexion convaincant sur un corps rigide cinématique en cas de collision. Est-ce l'approche habituelle si vous voulez ce type d'informations pour choisir si vous voulez diffuser des rayons ou saisir 3 points de contact (si disponibles) et prendre le produit croisé?
michael.bartnett