You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LibGDX Box2D物理体数量增多导致下落速度变慢问题排查

问题

用LibGDX Box2D开发测试游戏时,物理体数量为5个时下落速度正常;增加至10、12个及以上时,下落速度逐渐变慢。十几个物理体理论上不该影响重力效果,求排查原因。

代码示例
class GameViewActivity : ApplicationAdapter() {
    companion object {
        private const val SCALE = 2.0f
        const val PIXEL_PER_METER = 100f
        private const val TIME_STEP = 1 / 60f
        private const val VELOCITY_ITERATIONS = 6
        private const val POSITION_ITERATIONS = 20
        private const val VELOCITY_Y = -9.85f
        private const val VELOCITY_X = 0f
    }

    private var orthographicCamera: OrthographicCamera? = null
    private var world: World? = null
    private var batch: SpriteBatch? = null
    private var ground: Ground? = null

    private var discList = ArrayList<Disc>()
    private var shapeRenderer: ShapeRenderer? = null


    override fun create() {
        orthographicCamera = OrthographicCamera()
        orthographicCamera!!.setToOrtho(false, Gdx.graphics.width / SCALE, Gdx.graphics.height / SCALE)

        world = World(Vector2(VELOCITY_X, VELOCITY_Y), false)
        world!!.setContactListener(WorldContactListener())
        batch = SpriteBatch()
        val shape = PolygonShape()
        shape.setAsBox(orthographicCamera!!.viewportWidth, 2f)
        ground = Ground(world!!, shape)
        
        for (i in 1..12) {
            val d = Disc(world!!, 60f, 10f + i.toFloat()*2, 150f, 30f)
            discList.add(d)
        }
    }


    override fun render() {
        update()
        Gdx.gl.glClearColor(0.5f, 0.8f, 1f, 1f)
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)

        shapeRenderer = ShapeRenderer()
        shapeRenderer!!.begin(ShapeRenderer.ShapeType.Filled);
        shapeRenderer!!.color = Color.YELLOW;
        shapeRenderer!!.rect (
            0f,
            ground!!.body!!.position.y * PIXEL_PER_METER  - 12f / 2 / SCALE,
            orthographicCamera!!.viewportWidth * SCALE,
            2f * PIXEL_PER_METER
        )
        shapeRenderer!!.end();

        for (disc in discList) {
            val discRenderer = ShapeRenderer()
            discRenderer.begin(ShapeRenderer.ShapeType.Filled);
            discRenderer.color = disc.getColor()
            discRenderer.rect(
                300f,
                disc.body!!.position.y * PIXEL_PER_METER ,
                disc.getWidth() * SCALE,
                disc.getHeight() * SCALE
            )
            discRenderer.end()
        }
    }

    private fun update() {
        world!!.step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS)
        cameraUpdate()
    }

    private fun cameraUpdate() {
        orthographicCamera!!.update()
    }

}
原因排查与解决

核心问题:频繁创建ShapeRenderer导致性能暴跌

你的代码在render()方法里犯了两个严重的性能错误:

  1. 每次渲染都新建一个shapeRenderer实例,而非复用已有对象
  2. 循环绘制每个Disc时,都新建一个discRenderer,12个物体就会创建12个ShapeRenderer

ShapeRenderer是开销较大的OpenGL渲染对象,频繁创建销毁会触发频繁的垃圾回收(GC),导致游戏帧率骤降。而Box2D的物理模拟依赖固定时间步长(TIME_STEP = 1/60f),如果帧率低于60,每秒执行world.step()的次数不足,物理模拟速度就会变慢,表现为物体下落速度降低。

修复步骤

  1. 初始化阶段创建ShapeRenderer
    在create()方法中初始化shapeRenderer,避免每次渲染新建:
override fun create() {
    // ...其他初始化代码
    shapeRenderer = ShapeRenderer()
}
  1. 复用同一个ShapeRenderer绘制所有物体
    移除循环内的discRenderer,用同一个shapeRenderer批量绘制地面和所有圆盘:
override fun render() {
    update()
    Gdx.gl.glClearColor(0.5f, 0.8f, 1f, 1f)
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)

    shapeRenderer!!.begin(ShapeRenderer.ShapeType.Filled);
    // 绘制地面
    shapeRenderer!!.color = Color.YELLOW;
    shapeRenderer!!.rect (
        0f,
        ground!!.body!!.position.y * PIXEL_PER_METER  - 12f / 2 / SCALE,
        orthographicCamera!!.viewportWidth * SCALE,
        2f * PIXEL_PER_METER
    )
    // 绘制所有圆盘
    for (disc in discList) {
        shapeRenderer!!.color = disc.getColor()
        shapeRenderer!!.rect(
            300f,
            disc.body!!.position.y * PIXEL_PER_METER ,
            disc.getWidth() * SCALE,
            disc.getHeight() * SCALE
        )
    }
    shapeRenderer!!.end();
}
  1. 添加资源释放逻辑
    在dispose()方法中释放ShapeRenderer,避免内存泄漏:
override fun dispose() {
    shapeRenderer?.dispose()
    world?.dispose()
    batch?.dispose()
    // 释放其他资源
}
  1. 优化物理时间步处理(可选)
    如果帧率波动较大,建议用累计时间的方式调用world.step(),保证物理模拟速度稳定:
private var accumulator = 0f

private fun update() {
    val deltaTime = Gdx.graphics.deltaTime
    accumulator += deltaTime
    // 累计足够时间步就执行物理模拟
    while (accumulator >= TIME_STEP) {
        world!!.step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS)
        accumulator -= TIME_STEP
    }
    cameraUpdate()
}

内容的提问来源于stack exchange,提问作者jdleung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 04:55:05