Search code examples
javalibgdxbox2d

In box2d, can I call body.isActive() after body was destroyed?


In my game I'm implementing save/load state functionality, which restores part of the world, leaving the ground body untouched.

So when I click load button, I just save actors' coordinates, then remove all actors from stage and then re-create stage again using saved coordinates.

If actor owns a box2d body, it calls world.destroyBody() upon removal.

As result of a gameplay, I might get multiple actors having reference to same body.

So when I go over actor list and remove them one by one, it is possible that for some of them owned body was already destroyed (since it is shared).

Can I use body.isActive() check to see whether this body was already destroyed or that is not legal, since body is destroyed and should never be dereferenced from java again?

It looks like body.isActive() gives a false after body was dropped, or is it some kind of a side effect? Am I asking for problems (like famous box2d random crashing with not-so-helpful messages) calling any functions on already destroyed body?

Can I use code like this:

//since after ball is attached to magnet, they share 
// a body, and it might be that body is already dropped
if (body.isActive()) { 
            body = world.destroyBody(body);
        } 
        body = null;

What would be the best way to organise massive drop and recreate of part of the world?


Solution

  • Ok, that was working fine on my desktop, i.e. calling body.isActive() returns false on destroyed objects, and does not causes any stability issues.

    But when deployed to android phone, body.isActive() call on destroyed body returns true.

    Not trying to define a rule there, as I'm a newbie, but it looks like below:

    I would say, after body is destroyed (and it is destroyed down in native code), the behavior of any calls you do on the old reference is undefined or leads to immediate/later Box2d crashes.

    So I wouldn't do any calls on a dead box2d reference, therefore we cannot use body.isActive() after body is destroyed.

    The best practice would be assign your reference to null just after you've destroyed a body. Having a method destroyBody() which destroys body and always returns null allows you to do it in one line:

    public Body destroyBody(final Body body) {
     world.destroyBody(body); 
     return null; 
    } 
    ....
    body = destroyBody(body); //destroys body and set it to null in one line