Eu implementei um lançamento de varredura 2D AABBvsAABB no meu jogo, no entanto, estou tendo dificuldade em calcular o acerto normal do elenco de varredura.
Eu tenho a direção de varredura, as posições AAB B e xy min-maxs, primeiro e último tempos de batida para trabalhar, mas não a (s) aresta (s) em colisão ou a direção normal. Simplesmente não consigo conceber uma solução eficiente para esse problema específico. Alguma ideia? :)
*editar
É isso que eu tenho até agora - apenas uma implementação geral da varredura AABB de Gomez e Christer Ericson . Não há acerto normal, portanto, embora o cálculo normal seja um mistério para mim, não consigo produzir nenhuma resposta de colisão para o meu controlador de personagem.
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;
}