Ich habe einen 2D-AABBvsAABB-Sweep-Cast in mein Spiel implementiert, habe jedoch Schwierigkeiten, die Treffer-Normalen des Sweep-Casts zu berechnen.
Ich habe die Sweep-Richtung, sowohl die a- als auch die b-AABB-Position und die xy-Min-Max-Werte, die ersten und letzten Trefferzeiten, aber nicht die Kollisionskante (n) oder die normale Richtung. Ich kann mir einfach keine effiziente Lösung für dieses spezielle Problem vorstellen. Irgendwelche Ideen? :) :)
*bearbeiten
Dies ist, was ich bisher habe - nur eine allgemeine Implementierung des AABB-Sweeps von Gomez und Christer Ericson . Es gibt keinen normalen Treffer, daher ist mir die normale Berechnung zwar ein Rätsel, aber ich kann keine Kollisionsantwort für meinen Charakter-Controller erzeugen.
bool SweepVelAABBvsAABB(AABB a, AABB b, Vector2 v, out Vector2 outVel, out Vector2 norm )
{
outVel = v; //Initialise out velocity
norm = Vector2.zero;
if( AABBvsAABB(a,b) ) return true; //return early if a,b overlap
v = -v;
float hitTime = 0.0f;
float outTime = 1.0f;
if(v.x < 0.0f) //sweep is going right
{
if(b.max.x < a.min.x) return false;
if(a.max.x < b.min.x) hitTime = Mathf.Max( (a.max.x - b.min.x) / v.x, hitTime );
if(b.max.x > a.min.x) outTime = Mathf.Min( (a.min.x - b.max.x) / v.x, outTime );
}
else if(v.x > 0.0f) //sweep is going left
{
if(b.min.x > a.max.x) return false;
if(b.max.x < a.min.x) hitTime = Mathf.Max( (a.min.x - b.max.x) / v.x, hitTime );
if(a.max.x > b.min.x) outTime = Mathf.Min( (a.max.x - b.min.x) / v.x, outTime );
}
if(hitTime > outTime) return false;
//=================================
if(v.y < 0.0f) //sweep is going up
{
if(b.max.y < a.min.y) return false;
if(a.max.y < b.min.y) hitTime = Mathf.Max( (a.max.y - b.min.y) / v.y, hitTime );
if(b.max.y > a.min.y) outTime = Mathf.Min( (a.min.y - b.max.y) / v.y, outTime );
}
else if(v.y > 0.0f) //sweep is going down
{
if(b.min.y > a.max.y) return false;
if(b.max.y < a.min.y) hitTime = Mathf.Max( (a.min.y - b.max.y) / v.y, hitTime );
if(a.max.y > b.min.y) outTime = Mathf.Min( (a.max.y - b.min.y) / v.y, outTime );
}
if(hitTime > outTime) return false;
outVel = -v * hitTime;
return true;
}
quelle
Antworten:
Ich habe es geschafft, eine einfache und effiziente Lösung zu finden, indem ich die Trennachsen beobachtet habe.
quelle
Beachten Sie, wie normal der Treffer des A ist
sum(Normals of Vectors of Edges on B involved in collision)
. In geordneten Worten:Denken Sie daran, dass eine 'Kante' tatsächlich nur ein Scheitelpunkt sein kann ( wir kollidieren mit der Ecke eines anderen Felds).
Sie werden auch feststellen, dass dies für den normalen Treffer von B gilt .
quelle
Wenn ich das richtig verstehe, findet Ihr Algorithmus bisher die Position entlang der Bewegung von A, an der sich A und B gerade berühren.
Führen Sie mit dieser Position einen eindimensionalen Schnittpunkttest zwischen A und B auf allen drei Achsen durch. Eine (oder mehrere in Eckfällen) dieser Achsen haben keine Überlappung; Die Treffernormale sollte parallel zu dieser Achse und in Richtung von B nach A sein.
Wenn mehr als eine Achse keine Überlappung aufweist, haben Sie eine Kante oder Ecke perfekt getroffen. Sie können entweder willkürlich eine Option auswählen oder die Ergebnisse für eine "abgerundete" Ecke summieren.
quelle