Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm wondering how to remove the body from the world, because I found an error when I tried. I found following error.

java: /var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/Dynamics/b2World.cpp:134: void b2World::DestroyBody(b2Body*): Assertion 'IsLocked() == false' failed.

After some suggestion I tried for world.step()but then I found log file generated error.

share|improve this question
3  
Did you actually read that error? –  Lohoris Apr 10 '12 at 7:20
add comment

5 Answers

up vote 11 down vote accepted

From my little experience with box2d in libgdx, it can sometimes be difficult to isolate and resolve issues with exceptions which was only worsened by the latest port. Pre 2.2.1, I could easily remove bodies from the world without synchronization issues like you are experiencing but after migrating to the libgdx build that supported 2.2.1, I started seeing the same issues. The workaround for me, which was suggested by several people was that you cannot remove bodies from the world while the world is possibly being simulated.

Is there a possibility that you are attempting to remove a body from the world when the world is being stepped? Basically, if you try to do this, box2d doesn't like it so what you have to do is remove bodies outside of the world.step. What I did was added a utility class for the body's .userData with a bool isFlaggedForDelete which would get checked outside the world.step method.

public void sweepDeadBodies() {
   for (Iterator<Body> iter = CURRENT_WORLD.getBodies(); iter.hasNext();) {
     Body body = iter.next();
     if(body!=null) {
          YourCustomUserData data = (YourCustomUserData) body.getUserData();
          if(data.isFlaggedForDelete) {
          CURRENT_WORLD.destroyBody(body);
            body.setUserData(null);
            body = null;
          }
     }
}

If you run something like this right after your world.step, it should work. In your code where you are trying to destroy the body, just set it's .isFlaggedForDelete to true and it will get removed before the next world.step.

share|improve this answer
add comment

So we have your error:

/var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/Dynamics/b2World.cpp:134: void b2World::DestroyBody(b2Body*): Assertion 'IsLocked() == false' failed.

Let's break it down:

Most of the first part of this error is helpful directions to tell you where the error is happening.

/var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/Dynamics/b2World.cpp

It appears the error is being generated in a source file called b2World.cpp inside the directory structure shown. And it's happening:

:134:

On line 134.

Then it looks like,

void b2World::DestroyBody(b2Body*):

the function b2World:DestroyBody() which returns void and accepts a pointer to a b2Body is reporting the error.

That has finished the "where" part of the error, now it's telling us the "what". Looks like it's trying to assert that isLocked() is equal to false

Assertion `IsLocked() == false' failed.

But, look at that, it's failing. What could this mean? I would posit a guess that it really wants IsLocked() to be false but it turns out that IsLocked() is true, so it's failing. Now I've never used Box2D, but I'm guessing that means the body you're trying to destroy is locked. It's locked when it shouldn't be. How can you remedy this? Honestly if you haven't figured it out by now, you may want to take a step back and work on some more basic programming before coming back to this.

share|improve this answer
    
At a low level, you are of course correct. And it may be quite true that Siddarth is not researching his errors fully. But it is extremely common for the low level error to be misleading or confusing. Rubber Mallet's answer is far more relevant to the high level functionality of the framework. I don't think berating him to read more is an effective 'answer'. –  Myrddin Emrys Apr 10 '12 at 17:51
6  
@MyrddinEmrys When I see users post a series of questions like Siddarth, I think it's far more valuable that they learn some basics of how to solve problems in general, instead of being told how to solve this problem. –  Byte56 Apr 10 '12 at 18:04
    
Possibly, but this question, as asked, will be read by dozens if not hundreds of other people in the years to come who need help with this issue, and are getting this problem. You're not just helping Siddharth, you're helping all those future people too. Rubber Mallet's answer does that better. Specific instructions that are personal (to a specific person, not the question) should be comments. –  Myrddin Emrys Apr 10 '12 at 18:28
1  
@MyrddinEmrys I thought that too, then I thought if someone is looking for an answer to this exact question, they likely need the same help. –  Byte56 Apr 10 '12 at 18:30
add comment

Libgdx implementation is just bridge to native version so all the same rules apply.

Never try to remove a body/fixture/joint when the simulation is running.

Never try to remove a body/fixture/joint more than once.

Never leave pointers (aka references) to fixtures or joints when you delete the body.

To be extra cautious - maybe even little paranoid - I use this method to remove my bodies:

/**
 * Safe way to remove body from the world. Remember that you cannot have any
 * references to this body after calling this
 *
 * @param body
 *            that will be removed from the physic world
 */

public static void removeBodySafely(Body body) {
    //to prevent some obscure c assertion that happened randomly once in a blue moon
    final ArrayList<JointEdge> list = body.getJointList();
    while (list.size() > 0) {
        world.destroyJoint(list.get(0).joint);
    }
    // actual remove
    world.destroyBody(body);
}
share|improve this answer
add comment

The error says it all, you need to check if the world is locked in the moment that you want to remove the body

if(!world.isLocked())
     world.destroyBody(body)

that worked for me :)

share|improve this answer
add comment

This is the best way to do it, i read it in the Box2D manual. You have to call this just after CURRENT_WORLD.step(..,...,...);

Iterator<Body> i = CURRENT_WORLD.getBodies();
Body node=i.next();
while (i.hasNext()) {
    Body oBj=node;
    node=i.next();
    YourCustomUserData data = (YourCustomUserData) oBj.getUserData();
    if(data!=null &&  data.isFlaggedForDelete){
        CURRENT_WORLD.destroyBody(oBj);             
    }
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.