Warum gibt mir OnCollisionEnter von Unity keine Oberflächennormalen und wie bekomme ich sie am zuverlässigsten?


11

Das Kollisionsereignis von Unity gibt Ihnen ein Kollisionsobjekt , das Ihnen einige Informationen über die aufgetretene Kollision gibt (einschließlich einer Liste von ContactPoints mit Treffer-Normalen).

Was Sie jedoch nicht erhalten, sind Oberflächennormalen für den Collider, den Sie treffen. Hier ist ein Screenshot zur Veranschaulichung. Die rote Linie ist von ContactPoint.normalund die blaue Linie ist von RaycastHit.normal.

Geben Sie hier die Bildbeschreibung ein

Ist dies eine Instanz von Unity, die Informationen verbirgt, um eine vereinfachte API bereitzustellen? Oder erfassen Standard-3D-Echtzeit-Kollisionserkennungstechniken diese Informationen einfach nicht?

Und für den zweiten Teil der Frage, was ist ein todsicherer und relativ effizienter Weg, um eine normale Oberfläche für eine Kollision zu erhalten?

Ich weiß, dass Raycasting Oberflächennormalen liefert, aber es scheint, dass ich mehrere Raycasts durchführen muss, um dies für alle Szenarien zu erreichen (möglicherweise fehlt bei einer Kombination aus Kontaktpunkt und Normal der Collider beim ersten Cast, oder Sie müssen einen Durchschnitt von allen erstellen die Normalen der Kontaktpunkte, um das beste Ergebnis zu erzielen).

Meine aktuelle Methode:

  1. Sichern Sie die Collision.contacts[0].pointentlang seiner Treffer normal

  2. Raycast den negierten Treffer normal für float.MaxValue, aufCollision.collider

  3. Wenn dies fehlschlägt, wiederholen Sie die Schritte 1 und 2 mit der nicht negierten Normalen

  4. Wenn dies fehlschlägt, versuchen Sie die Schritte 1 bis 3 mit Collision.contacts[1]

  5. Wiederholen Sie 4 bis erfolgreich oder bis alle Kontaktpunkte erschöpft sind.

  6. Gib auf, kehre zurück Vector3.zero.

Dies scheint alles zu erfassen, aber all diese Raycasts machen mich mulmig, und ich bin mir nicht sicher, wie ich testen soll, ob dies für genügend Fälle funktioniert. Gibt es einen besseren Weg?

BEARBEITEN Wenn dies bei 3D-Kollisionen wirklich so ist, wäre ein Überblick darüber, warum dies im Allgemeinen der Fall ist, genauso willkommen wie etwas, das für Unity spezifisch ist.


Ist das nur aus Neugier oder versuchen Sie etwas zu tun und stecken zu bleiben? Das heißt, warum brauchst du die Oberfläche normal? Stellen Sie eine Frage zu dem Effekt, den Sie erzielen möchten, anstatt wie Sie eine Lösung für ein nicht angegebenes Problem "beheben" können, und jemand kann Ihnen möglicherweise bei der Lösung helfen. :)
Sean Middleditch

@ SeanMiddleditch Ich stimme nicht zu. Die Frage ist gut gestellt und genau das, wonach ich gesucht habe. Diese Frage und ihre Antworten haben mir geholfen, einige Dinge zu korrigieren, die ich falsch gemacht habe.
SteakOverflow

Antworten:


12

Dies ist wirklich genau so, wie es mit Kollisionen ist. Nicht nur 3D, sondern auch 2D. Nehmen Sie das folgende Beispiel:

Überlappende AABBs

Die grünen und roten AABBs kollidieren und der Kontaktverteiler ist der blaue Bereich. Die Kontaktpunkte befinden sich irgendwo im blauen Bereich (genau dort, wo sie je nach Algorithmus variieren können, aber die Ecken, in denen sich Blau / Rot / Grün trifft, sind ideal).

Welche Oberflächennormale sollte zurückgegeben werden? Die Oberkante des roten AABB oder die linke Kante? Wenn die grüne Box herunterfällt, können wir die Oberkante vielleicht vernünftigerweise erraten. Wenn es sich nach rechts bewegt, können wir vielleicht den linken Rand vernünftigerweise erraten. Was ist, wenn es sich nach unten und rechts bewegt? Nehmen wir die Achse der geringsten Durchdringung? Die Geschwindigkeitsachse der größten Geschwindigkeit? Eine Heuristik von beiden? Was wäre, wenn die Kisten genau an den Ecken kollidiert wären?

Erweitern Sie dies auf eine komplexe 3D-Oberfläche, die möglicherweise aus Hunderten von Tris / Flächen besteht. Sie werden immer noch nur eine kleine Anzahl idealer Kontaktpunkte haben. Welche Oberflächennormale sollte zurückgegeben werden? Die durchschnittliche Oberflächennormale über das gesamte Tri-Mesh (was für die meisten Objekte keinen Sinn macht)? Die Punkte direkt "unter" den Ecken der Kollisionsbox (die für die meisten anderen Formen nicht gut definiert sind)? Versuchen Sie, die Fläche zu finden, die den erzeugten Kontaktpunkten am nächsten liegt (was einen zweiten Durchgang erfordern würde, da Kontaktpunkte nicht direkt aus Maschenflächen berechnet werden)? Wenn Sie das nächstgelegene Gesicht finden, nehmen Sie die Normalen des Gesichts oder interpolieren Sie die Eckpunkte des Gesichts am Kontaktpunkt, um die richtige Normalen für "glatte" Objekte zu erhalten?

Das Hauptproblem besteht darin, dass die Kontaktpunkte nicht alle Kontaktpunkte sind. In vielen Fällen wäre das schließlich eine unendliche Menge von Punkten. Es sind nur einige Punkte, die gut verteilt sind und es vernünftigerweise möglich machen, die physikalische Reaktion durch Aufbringen von Kräften an diesen Punkten zu approximieren, um die kollidierenden Objekte auf eine reaslitisch-artige Weise herumzuschieben. Die spezifischen Punkte / Orte des tatsächlichen Objektkontakts werden hinter einem vereinfachten mathematischen Modell abstrahiert. Daher macht die Vorstellung einer bestimmten Oberflächennormalen des Kontakts im allgemeinen Fall einfach wenig Sinn.

Natürlich können Sie mit spezifischeren Einschränkungen und Einschränkungen für Ihre Objekte, Ihre Welt und Ihre Bewegung alternative Kollisionsalgorithmen erstellen, die Sie über die Oberflächennormale informieren. Wenn wir im obigen 2D-Fall davon ausgehen, dass sich die Kästchen niemals drehen und dass wir die Relativgeschwindigkeit und die letzte Position der einzelnen Kästchen kennen, könnten wir mithilfe der kontinuierlichen Kollisionserkennung genau herausfinden, wann sie kollidieren würden und welche Merkmale kollidieren, und uns das liefern genaues Merkmal, bei dem eine Kollision aufgetreten ist, das dann als Kontakt- / Kollisions- / Oberflächennormale verwendet werden kann. Platformer-Spiele basieren ausschließlich auf solchen Annahmen und speziellen Tricks (weshalb die Verwendung einer allgemeinen Physikbibliothek wie Box2D oder Havok oder des Lichts niemals die enge, präzise Kontrolle erzeugt, die Sie bei klassischen Platformern wie Mario oder Sonic finden; ich würde es nicht tun will es sagen '

Allgemeine Newtonsche Physikbibliotheken, wie sie in Unity3D verwendet werden, können solche Vereinfachungen und Annahmen nicht vornehmen. Daher erhalten Sie keine Kollisionsoberflächennormalen, sondern einen Kontaktverteiler, der im Allgemeinen bis zu Kontaktpunkten vereinfacht ist, und das war's.


Dies ist eine fantastische Antwort und genau das, wonach ich gesucht habe, danke. Das spezifische Problem bestand darin, bei einer Kollision einen überzeugenden Reflexionsvektor auf einem kinematischen starren Körper zu erhalten. Ist der übliche Ansatz, wenn Sie möchten, dass diese Art von Informationen auswählt, ob Sie Raycast senden oder 3 Kontaktpunkte (falls verfügbar) abrufen und das Kreuzprodukt verwenden möchten?
michael.bartnett
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.