简体   繁体   English

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

[英]Reuse Box2D objects in LibGDX game (pooling)

I'm working in a game in which I spawn an object every 1-3 seconds. 我正在一个游戏中工作,我每隔1-3秒就产生一个物体。 This game object contains some assets for renderization purposes and a Box2D body. 此游戏对象包含一些用于渲染目的的资源和一个Box2D正文。 The thing is that I don't want to create thousands of objects. 问题是我不想创建数千个对象。 Instead, I would like to reuse them, resetting its properties (position, friction, etc.) and not creating a brand new object. 相反,我想重用它们,重置它的属性(位置,摩擦等)而不是创建一个全新的对象。 I think that the best way to do this is implementing a pool of this objects but I'm concerned about it because after search for some info I've found several developers reporting memory leaks because all the objects created by Box2D internally. 我认为最好的方法是实现这个对象的池,但是我很关心它,因为在搜索了一些信息之后我发现有几个开发人员报告了内存泄漏,因为Box2D内部创建了所有对象。

What do you think is the best way to do this? 您认为最好的方法是什么?

This is the class that I use to represent each game object: 这是我用来表示每个游戏对象的类:

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 */
}

This seems like a case of early optimization and may not yield the results you are looking for. 这似乎是早期优化的情况,可能无法产生您正在寻找的结果。

Consider: 考虑:

  1. All those objects sitting your "pool" are still registered internally in Box2D as objects. 坐在“池”中的所有对象仍然在Box2D内部注册为对象。 Will collision checking be performed on them? 是否会对它们进行碰撞检查? Will collision response? 碰撞响应? Will their usertag be pointing to an object in the "pool" (user tags are often used to reference the "owner" of the body)? 他们的usertag是否会指向“池”中的对象(用户标签通常用于引用正文的“所有者”)?
  2. There are life cycle issues associated with all the values in an object...you will have to be careful to manage the values (position is easy, but collision flags etc. gets deeper) for each object you take into and pull out of the pool. 存在与对象中的所有值相关联的生命周期问题...您必须小心管理每个对象的位置(位置很容易,但碰撞标记等变得更深)池。 That sounds error prone. 这听起来容易出错。

If you are really only creating/destroying a single object every second, that does not seem like much of a performance/memory hit. 如果你真的只是每秒创建/销毁一个对象,那么这似乎不会影响性能/内存。 If you are creating hundreds, that is a different story. 如果你要创造数百个,那就是另一个故事。 I wrote a game where I had bullets being generated at a rate of 10-20 per second...each was derived from an "Entity" base class which is a composite (I called the class "Slug" I think). 我写了一个游戏,我以每秒10-20的速度生成子弹......每个都来自一个“实体”基类,这是一个复合(我认为我称之为“Slug”类)。 The "Slug" class held the body, the sprite, the collision handling logic, etc. When it collided or after a few seconds, it "died" and went into the pool. “Slug”类拥有身体,精灵,碰撞处理逻辑等。当它碰撞或几秒钟后,它“死亡”并进入游泳池。 Pulling it from the pool caused it to re-create the body and I did not see this as a performance or memory bottleneck. 从池中拉出它会导致它重新创建主体,我没有将其视为性能或内存瓶颈。

It did not recreate the parts that may cause larger allocation or were not necessary (eg the sprite). 它没有重新创建可能导致更大分配或不必要的部分(例如精灵)。 These don't need to be reclaimed until it is actually deleted from the pool because it is really just a reference to a sprite sheet that is shared. 在实际从池中删除它们之前不需要回收它们,因为它实际上只是对共享的精灵表的引用。 A specific "Init(...)" method was associated with the class so that the memory allocation could be separate from the initialization. 特定的“Init(...)”方法与类相关联,以便内存分配可以与初始化分开。

Your mileage may vary, of course. 当然,您的里程可能会有所不同。 But I think you should look to see if it is really a problem (ie prototype it) before you build infrastructure to fix it. 但是我认为你应该在构建基础设施来修复它之前看看它是否真的是一个问题(即原型)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM