发射大量子弹后,Box2D碰撞检测失败

时间:2019-04-29 12:36:06

标签: kotlin libgdx box2d

我正在做一个物理游戏,遇到一个奇怪的错误:有时,在发射很多子弹后,碰撞检测开始失败。

在以下GIF中可以看到,碰撞仅在平台的一半上起作用,这很奇怪。此外,还启用了Box2D调试渲染器,并且还可以看到该平台是一个整体。

Bug

这是我如何使此错误发生的原因,因为它仅在发射大量子弹后才发生(开始时一切正常):

Replicate

注释:
-项目符号的bullet字段设置为true
-我将播放器的bullet字段设置为true,没有任何区别
-玩家1米x 1米
-玩家和子弹为DynamicBodies,平台为StaticBodies
-地图接近(0,0),尽管它在负数(-1.5)处有点偏,但我怀疑它是否重要
-categoryBitsmaskBits是正确的(碰撞应该发生,并且确实发生,但有故障)
-子弹消失后,尸体数量与游戏开始时的尸体数量相同(因此实际上已被销毁)
-World的重力为(0,-25f)
-游戏以60fps的速度运行

这里是Box2D时间步代码,类似于libGDX wiki中的步代码:

companion object {
    private const val TIME_STEP = 1f / 300f
    private const val VELOCITY_ITERATIONS = 6
    private const val POSITION_ITERATIONS = 2
}

private var accumulator = 0f

override fun update(deltaTime: Float) {
    accumulator += Math.min(deltaTime, 0.25f)
    while (accumulator >= TIME_STEP) {
        world.step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS)
        accumulator -= TIME_STEP
    }
}

我尝试更改:
-TIME_STEP较低,例如1 / 60f
-VELOCITY_ITERATIONS更高,达到8
-POSITION_ITERATIONS更高,达到6
-VELOCITY_ITERATIONSPOSITION_ITERATIONS到100
而且没有(明显的)区别。

关注点
这个漏洞百出的平台似乎至少在一半时就开始表现得像子弹(它不会与其他子弹或玩家相撞)。那么在大量categoryBitsmaskBits之后,也许是由于池化,它的world.createBody()world.destroyBody()是否可以即时更改?

那么在这种情况下如何使碰撞不失败?

1 个答案:

答案 0 :(得分:2)

我终于设法修复了它。

我发现的解决方案是遍历每个具有主体的实体并调用refilter(),这似乎可以解决该问题:

engine.getEntitiesFor(Family.one(BodyComponent::class.java).get()).forEach {
    it.body.body.fixtureList.first().refilter()
}

将来,我只能在需要时调用refilter()(如果我可以确定何时必须调用它),而不是在每一帧都调用它,但现在可以使用。

refilter()外部更改实体的filterData(更改其categoryBitsmaskBits)之后,您似乎应该呼叫FixtureDef,但是我似乎并没有这样做(或者可能我缺少了一些东西),所以有点奇怪。