我在一个非常简单的 XNA 4 测试游戏中使用 Farseer Physics Engine 3.3.1。(注意:我也标记了这个 Box2D,因为 Farseer 是 Box2D 的直接端口,我很乐意接受解决这个问题的 Box2D 答案。)
在这个游戏中,我创造了两个身体。第一个主体是使用BodyFactory.CreateCircle
and创建的BodyType.Dynamic
。可以使用键盘(设置 Body.LinearVelocity)来移动这个身体。第二个主体是使用BodyFactory.CreateRectangle
and创建的BodyType.Static
。这个身体是静止的,从不移动。
然后我使用这段代码来计算两个物体碰撞时的碰撞力:
staticBody.FixtureList[0].AfterCollision += new AfterCollisionEventHandler(AfterCollision);
protected void AfterCollision(Fixture fixtureA, Fixture fixtureB, Contact contact)
{
float maxImpulse = 0f;
for (int i = 0; i < contact.Manifold.PointCount; i++)
maxImpulse = Math.Max(maxImpulse, contact.Manifold.Points[i].NormalImpulse);
// maxImpulse should contain the force of the collision
}
如果这两个主体都设置为IgnoreCCD=true
. 我可以 100% 可靠地计算出它们之间的碰撞力。完美的。
但问题是:如果我将主体设置为 IgnoreCCD=false,那么该代码将变得非常不可预测。AfterCollision 被可靠地调用,但由于某种原因,NormalImpulse 大约有 75% 的时间为0,因此仅记录了大约四分之一的碰撞。更糟糕的是,由于完全随机的原因,NormalImpulse 似乎为零。动态物体可以以几乎完全相同的方式连续 10 次与静态物体碰撞,并且只有 2 或 3 次碰撞会记录到大于零的 NormalImpulse。在两个身体上设置IgnoreCCD=true
立即解决了问题,但随后我失去了连续的物理检测。
为什么会发生这种情况,我该如何解决?
这是一个简单的 XNA 4 解决方案的链接,该解决方案演示了这个问题的实际效果: http ://www.mediafire.com/?a1w242q9sna54j4