kotlin - 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
担忧:
被窃听的平台似乎开始表现得像一颗子弹(它不会与其他子弹或玩家碰撞),至少在中途。那么它的categoryBits
and是否可以在经过大量andmaskBits
之后即时更改,也许是由于池化?world.createBody()
world.destroyBody()
那么在这种情况下我应该怎么做才能让碰撞不失败呢?
解决方案
我终于设法修复它。
我找到的解决方案是遍历每个具有 body 和 call 的实体refilter()
,这似乎可以解决它:
engine.getEntitiesFor(Family.one(BodyComponent::class.java).get()).forEach {
it.body.body.fixtureList.first().refilter()
}
将来,我可以refilter()
仅在需要时调用(如果我可以确定何时必须调用它)而不是每帧调用它,但它现在可以使用。
看起来你应该refilter()
在你改变filterData
身体的 (改变它的categoryBits
or maskBits
)之后打电话FixtureDef
,但我似乎没有这样做(或者我可能遗漏了一些东西),所以这有点奇怪。
推荐阅读
- install4j - Install4j 需要时间来清理自己
- java - org.xml.sax.SAXParseException;尝试从请求中获取 xml 输入时文件过早结束
- node.js - 如何在 NodeJS 中使用带有图表和谷歌地图的 html 生成 PDF
- rust - Rust 中结构字段的多态更新
- android - Facebook 广告活动未显示应用安装数据
- c# - 使用 Html.Raw 时如何运行 Html 和 Url 助手 - ASP NET MVC
- excel - Excel:如何将千 (k) 和百万 ($m) 的缩写转换为数值?
- go - Go 中并发数据收集的最佳方式是什么,为什么?
- java - 如何完全阻止 JUnit 套件的执行?
- php - 我正在尝试使用 php 上传音乐和图像文件并插入数据表,但我的代码不起作用