简体   繁体   English

Box2d内存泄漏

[英]Box2d Memory Leak

I have determined that box2d is causing a memory leak. 我已经确定box2d导致内存泄漏。 After just 20 minutes, it goes from occupying 10% of the application memory, all the way to 50%. 仅仅20分钟后,它占用了10%的应用程序内存,一直到50%。 The object count at the start of the game is 100,000. 游戏开始时的对象数为100,000。 That number (even after GC) rises to above 1.5 million. 这个数字(即使在GC之后)上升到150万以上。 The application is not only slowed on android, but desktop starts to run poorly too. 该应用程序不仅在Android上速度变慢,而且桌面开始运行也很糟糕。 Initially it runs fine, but after 5 minutes it starts to look laggish. 最初运行良好,但5分钟后开始看起来很迟钝。 I will link the relevant code below. 我将链接下面的相关代码。 But first, here is some more info : 但首先,这里有更多信息:

I needed to dynamically change the fixture size for these bodies. 我需要动态地改变这些物体的夹具尺寸。 So my solution is to destroy/recreate the fixtures to the appropriate size every frame. 所以我的解决方案是每帧破坏/重新创建适当大小的灯具。 There are a total of 8 objects (all the same as the code below) that use box2d. 使用box2d的共有8个对象(与下面的代码完全相同)。 These objects are the only potential leaking point I believe. 这些对象是我认为唯一潜在的泄漏点。

The method below is called every frame for the 8 enemy objects I mentioned earlier. 对于我前面提到的8个敌人对象,每个帧都调用下面的方法。 I should also say that the value 'true' IS passed into this method each call. 我还应该说每次调用都会将值'true'传递给此方法。 As you will see, I am disposing of the fixtures and the shapes, so I'm not sure how a memory leak could occur. 正如您将看到的,我正在处理灯具和形状,因此我不确定如何发生内存泄漏。

private void createFixtures(boolean remove) {

    if (remove) {
        if (fixture_inner != null) {
            if(body.getFixtureList().contains(fixture_inner, false)) {
                body.destroyFixture(fixture_inner);
            }
        }
        if (fixture_outer != null) {
            if(body.getFixtureList().contains(fixture_outer, false)) {
                body.destroyFixture(fixture_outer);
            }
        }
        if (fixture_gap != null) {
            if(body.getFixtureList().contains(fixture_gap, false)) {
                body.destroyFixture(fixture_gap);
            }
        }
    }

    if (getInnerBounds() != null) {
        FixtureDef fixtureDef_inner = new FixtureDef();
        PolygonShape shape_inner = new PolygonShape();
        shape_inner.set(getInnerBounds().getTransformedVertices());
        fixtureDef_inner.shape = shape_inner;
        fixtureDef_inner.filter.categoryBits = Config.CATEGORYBIT_BLOCKER;
        fixtureDef_inner.filter.maskBits = Config.CATEGORYBIT_PLAYER;
        fixtureDef_inner.isSensor = true;
        fixture_inner = body.createFixture(fixtureDef_inner);
        BlockerFixtureUserData fixtureUserData_inner = new BlockerFixtureUserData(this, gameObjects.indexOf(this, false));
        fixture_inner.setUserData(fixtureUserData_inner);

        shape_inner.dispose();
    }

    if (getOuterBounds() != null) {
        FixtureDef fixtureDef_outer = new FixtureDef();
        PolygonShape shape_outer = new PolygonShape();
        shape_outer.set(getOuterBounds().getTransformedVertices());
        fixtureDef_outer.shape = shape_outer;
        fixtureDef_outer.filter.categoryBits = Config.CATEGORYBIT_BLOCKER;
        fixtureDef_outer.filter.maskBits = Config.CATEGORYBIT_PLAYER;
        fixtureDef_outer.isSensor = true;
        fixture_outer = body.createFixture(fixtureDef_outer);
        BlockerFixtureUserData fixtureUserData_outer = new BlockerFixtureUserData(this, gameObjects.indexOf(this, false));
        fixture_outer.setUserData(fixtureUserData_outer);

        shape_outer.dispose();
    }

    if (getGapBounds() != null) {
        FixtureDef fixtureDef_gap = new FixtureDef();
        PolygonShape shape_gap = new PolygonShape();
        shape_gap.set(getGapBounds().getTransformedVertices());
        fixtureDef_gap.shape = shape_gap;
        fixtureDef_gap.filter.categoryBits = Config.CATEGORYBIT_BLOCKERGAP;
        fixtureDef_gap.filter.maskBits = Config.CATEGORYBIT_PLAYER;
        fixtureDef_gap.isSensor = true;
        fixture_gap = body.createFixture(fixtureDef_gap);
        BlockerFixtureUserData fixtureUserData_gap = new BlockerFixtureUserData(this, gameObjects.indexOf(this, false));
        fixture_gap.setUserData(fixtureUserData_gap);

        shape_gap.dispose();
    }
}

The player also has a similar method that does the same thing, just specified for the player. 玩家也有类似的方法做同样的事情,只为玩家指定。

 private void createFixture(boolean remove) {

    if (remove) {
        body.destroyFixture(fixture);
    }

    BodyDef bodyDef = new BodyDef();
    bodyDef.type = BodyDef.BodyType.DynamicBody;
    bodyDef.position.set(0, 0);
    body = world.createBody(bodyDef);
    FixtureDef fixtureDef = new FixtureDef();
    CircleShape circle = new CircleShape();
    circle.setRadius(getWidth() / 2);
    circle.setPosition(new Vector2(0, getY() + getHeight() / 2));
    fixtureDef.shape = circle;
    fixtureDef.filter.categoryBits = Config.CATEGORYBIT_PLAYER;
    fixture = body.createFixture(fixtureDef);

    circle.dispose();
}

The disposing of the world is in my main game class. 处理世界是我的主要游戏类。 But it's important to note (maybe?) that this game only has 1 screen as of right now. 但重要的是要注意(也许?)此游戏目前只有1个屏幕。

If there is any additional information you may need, feel free to ask! 如果您可能需要任何其他信息,请随时提出! Thanks a million! 太感谢了!

My problem was that I was instantiating a body in the player createFixture method that is called every frame to edit the fixture sizes. 我的问题是我在播放器createFixture方法中实例化一个体,每个帧都调用它来编辑夹具大小。 I moved this to the constructor. 我把它移到了构造函数中。

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

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