首页 > 解决方案 > Box2D 碰撞检测在发射大量子弹后失败

问题描述

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

从下面的 GIF 中可以看出,碰撞只在一半的平台上起作用,这很奇怪。另外,启用了Box2D调试渲染器,也可以看出平台是单体的。

漏洞

以下是我如何让这个错误发生,因为它只有在发射大量子弹后才会发生(一开始一切正常):

复制

注意:
- 子弹的bullet场地设置为true
- 我将玩家的bullet场地设置为true,没有区别
- 玩家是 1 米乘 1 米
- 玩家和子弹DynamicBodies和平台是StaticBodies
- 地图靠近( 0, 0),虽然它有点负面(-1.5),但我怀疑它是否重要
-categoryBits并且maskBits是正确的(碰撞应该发生,并且确实发生了,但是有故障)
- 子弹消失后,数量身体与游戏开始时相同(因此它们实际上已被摧毁)
-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
-更改为 100 ,VELOCITY_ITERATIONS并且 没有(明显的)差异。POSITION_ITERATIONS

担忧:
被窃听的平台似乎开始表现得像一颗子弹(它不会与其他子弹或玩家碰撞),至少在中途。那么它的categoryBitsand是否可以在经过大量andmaskBits之后即时更改,也许是由于池化?world.createBody()world.destroyBody()

那么在这种情况下我应该怎么做才能让碰撞不失败呢?

标签: kotlinlibgdxbox2d

解决方案


我终于设法修复它。

我找到的解决方案是遍历每个具有 body 和 call 的实体refilter(),这似乎可以解决它:

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

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

看起来你应该refilter()在你改变filterData身体的 (改变它的categoryBitsor maskBits)之后打电话FixtureDef,但我似乎没有这样做(或者我可能遗漏了一些东西),所以这有点奇怪。


推荐阅读