我怎样才能在冲突解决中对推出向量进行排序?
How can I go about sorting pushout vectors in collision resolution?
最近我一直在研究我的游戏,到目前为止我的 SAT 碰撞检测分辨率工作正常(我可以检测到两个多边形相交并找出正确的矢量将一个推离另一个('pushout' 向量))
但是,在将推出向量应用于其他多边形时,我遇到了 运行 问题。当一个多边形与 2 个或更多多边形接触时,我最终会得到 2 个或更多推出向量,需要以正确的顺序应用这些向量以获得真实的结果(也就是不要通过其他多边形出现故障或卡在角落上不存在)
目前,我应用每个推向量,每次应用它时,我检查多边形是否仍然与它碰撞的其他多边形相交,如果是,我继续应用其余的向量。如果没有,就停止应用,因为它们不再碰撞了。
问题在于我需要按特定顺序应用向量,而不仅仅是列表中的其他顺序。我不知道订购它们的好的解决方案。
这是我的代码(collider 是需要应用推出向量的对象)(otherColliders 是碰撞器相交的碰撞器列表):
List<Vector2> pushoutVectors = getPushoutVectors(otherColliders);
foreach (Vector2 pushout in pushoutVectors)
{
collider.Transform.Position += pushout;
if (!collider.checkForIntersecting(otherColliders))
break;
}
下图是我目前的问题。有没有办法在 (0, 1) 之前获取向量 (-1, 0)?
解决方案是根据与每个对撞机中心的距离进行排序。不要从原点或类似点排序 - 按升序排列的两个碰撞器中心之间的距离排序。这可确保正确应用推出矢量,并且不会发生剪裁或卡住。
示例代码:
public struct Hit
{
public Collider Me;
public Collider Other;
public Vector2 Pushout;
public float getCenteredDistanceFromOtherSquared()
{
return Vector2.DistanceSquared(Me.getWorldBounds().Center, Other.getWorldBounds().Center);
}
}
List<Hit> hits = getHits(otherColliders);
// note: this is a long function name for the sake of being clear.
// it returns the distance between the 'collider' and the 'other' collider in the collision
// its squared simply because we just need to order by size not get the actual size, so its just to prevent use of a performance-costly sqrt function
List<Hit> sortedhits = hits.OrderBy(x => x.getCenteredDistanceFromOtherSquared()).ToList();
foreach (Hit hit in sortedhits)
{
// apply pushout
collider.Transform.Position += hit.Pushout;
// check if we're still colliding with any other colliders
// if we aren't, stop applying hits
// if we are, keep applying hits
// this is to prevent getting stuck on edges and such
if (!collider.checkForIntersecting(otherColliders))
break;
}
最近我一直在研究我的游戏,到目前为止我的 SAT 碰撞检测分辨率工作正常(我可以检测到两个多边形相交并找出正确的矢量将一个推离另一个('pushout' 向量))
但是,在将推出向量应用于其他多边形时,我遇到了 运行 问题。当一个多边形与 2 个或更多多边形接触时,我最终会得到 2 个或更多推出向量,需要以正确的顺序应用这些向量以获得真实的结果(也就是不要通过其他多边形出现故障或卡在角落上不存在)
目前,我应用每个推向量,每次应用它时,我检查多边形是否仍然与它碰撞的其他多边形相交,如果是,我继续应用其余的向量。如果没有,就停止应用,因为它们不再碰撞了。
问题在于我需要按特定顺序应用向量,而不仅仅是列表中的其他顺序。我不知道订购它们的好的解决方案。
这是我的代码(collider 是需要应用推出向量的对象)(otherColliders 是碰撞器相交的碰撞器列表):
List<Vector2> pushoutVectors = getPushoutVectors(otherColliders);
foreach (Vector2 pushout in pushoutVectors)
{
collider.Transform.Position += pushout;
if (!collider.checkForIntersecting(otherColliders))
break;
}
下图是我目前的问题。有没有办法在 (0, 1) 之前获取向量 (-1, 0)?
解决方案是根据与每个对撞机中心的距离进行排序。不要从原点或类似点排序 - 按升序排列的两个碰撞器中心之间的距离排序。这可确保正确应用推出矢量,并且不会发生剪裁或卡住。
示例代码:
public struct Hit
{
public Collider Me;
public Collider Other;
public Vector2 Pushout;
public float getCenteredDistanceFromOtherSquared()
{
return Vector2.DistanceSquared(Me.getWorldBounds().Center, Other.getWorldBounds().Center);
}
}
List<Hit> hits = getHits(otherColliders);
// note: this is a long function name for the sake of being clear.
// it returns the distance between the 'collider' and the 'other' collider in the collision
// its squared simply because we just need to order by size not get the actual size, so its just to prevent use of a performance-costly sqrt function
List<Hit> sortedhits = hits.OrderBy(x => x.getCenteredDistanceFromOtherSquared()).ToList();
foreach (Hit hit in sortedhits)
{
// apply pushout
collider.Transform.Position += hit.Pushout;
// check if we're still colliding with any other colliders
// if we aren't, stop applying hits
// if we are, keep applying hits
// this is to prevent getting stuck on edges and such
if (!collider.checkForIntersecting(otherColliders))
break;
}