Java 在LibGDX游戏中重用Box2D对象(池)

Java 在LibGDX游戏中重用Box2D对象(池),java,libgdx,box2d,object-pooling,Java,Libgdx,Box2d,Object Pooling,我在玩一个游戏,每1-3秒产生一个物体。此游戏对象包含一些用于渲染的资源和Box2D实体。问题是我不想创建成千上万的对象。相反,我希望重用它们,重置其属性(位置、摩擦力等),而不是创建一个全新的对象。我认为最好的方法是实现一个对象池,但我很担心,因为在搜索一些信息后,我发现几个开发人员报告内存泄漏,因为所有对象都是由Box2D内部创建的 你认为最好的方法是什么 这是我用来表示每个游戏对象的类: public class GameObject extends Box2dGameObject {

我在玩一个游戏,每1-3秒产生一个物体。此游戏对象包含一些用于渲染的资源和Box2D实体。问题是我不想创建成千上万的对象。相反,我希望重用它们,重置其属性(位置、摩擦力等),而不是创建一个全新的对象。我认为最好的方法是实现一个对象池,但我很担心,因为在搜索一些信息后,我发现几个开发人员报告内存泄漏,因为所有对象都是由Box2D内部创建的

你认为最好的方法是什么

这是我用来表示每个游戏对象的类:

public class GameObject extends Box2dGameObject {

    private static final float WIDTH = 0.85f;
    private static final float HEIGHT = 1;

    private Animation animationDying;
    private Animation animationFalling;
    private Animation animationIdle;
    private Animation animationJumping;
    private Animation animationRunning;

    private Body body;

    public GameObject(Vector2 position, World world) {
        super(position, world);

        init();
    }

    private void init() {
        super.init();

        dimensions.set(WIDTH, HEIGHT);

        /* Get assets */
        animationDying = Assets.instance.pirate.animationDying;
        animationFalling = Assets.instance.pirate.animationFalling;
        animationIdle = Assets.instance.pirate.animationIdle;
        animationJumping = Assets.instance.pirate.animationJumping;
        animationRunning = Assets.instance.pirate.animationRunning;

        /* Set default animation */
        setAnimation(animationIdle);

        body = createBox2dBody();  
    }

    private Body createBox2dBody() {
        BodyDef bodyDef = new BodyDef();
        bodyDef.fixedRotation = true;
        bodyDef.position.set(position);
        bodyDef.type = BodyType.DynamicBody;

        PolygonShape shape = new PolygonShape();
        shape.setAsBox(WIDTH / 2, HEIGHT / 2);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.density = 1;
        fixtureDef.friction = 1;
        fixtureDef.shape = shape;

        Body body = world.createBody(bodyDef);
        fixture = body.createFixture(fixtureDef);

        shape.dispose();

        return body;
    }

    /* More code omitted */
}

这似乎是一个早期优化的案例,可能不会产生您想要的结果

考虑:

  • 所有位于“池”中的对象仍然在Box2D内部注册为对象。是否对它们执行碰撞检查?碰撞会有反应吗?他们的用户标签是否指向“池”中的对象(用户标签通常用于引用主体的“所有者”)
  • 存在与数据库中所有值相关的生命周期问题 对象…您必须小心地管理池中每个对象的值(位置很容易,但冲突标志等会变得更深)。这听起来很容易出错
  • 如果你真的每秒钟只创建/销毁一个对象,那么这看起来不像是对性能/内存的影响。如果你创造了数百个,那就不同了。我写了一个游戏,其中子弹以每秒10-20次的速度生成……每个子弹都来自一个“实体”基类,它是一个复合类(我想我称这个类为“Slug”)。“Slug”类持有身体、精灵、碰撞处理逻辑等。当它碰撞或几秒钟后,它“死亡”并进入池中。将其从池中拉出会导致它重新创建主体,我不认为这是性能或内存瓶颈

    它没有重新创建可能导致更大分配或不必要的部分(例如精灵)。在从池中实际删除之前,不需要回收这些文件,因为它实际上只是对共享的精灵工作表的引用。一个特定的“Init(…)”方法与该类相关联,因此内存分配可以与初始化分离


    当然,您的里程数可能会有所不同。但我认为,在构建解决问题的基础设施之前,您应该先看看这是否真的是一个问题(即原型问题)。

    重新发布相同的问题并不好。。。但是,我相信您可以重用BodyDef、Shape、FixtureDef来创建新的实体。实体不能合并,因为它们实际上是由外部本机(C++)模块创建和维护的。此外,我认为那些“几个报告内存泄漏的开发人员”都是错误的,因为在这种情况下,内存泄漏毫无意义。您可能会有非常奇怪的行为,但没有内存泄漏。。。