Search code examples
androidbox2dandenginenative-codephysics-engine

Crash when destroying bodies


When I destroy an object made of several bodies connected by joints, my application crashes without an error. Of course I did some research and found that this happens when one destroys bodies while the physics engine calculates a step. So I just add the bodies to a list and destroy them in onUpdate(), but that didn't help. The funny thing is that destroying simple bodies works like a charm even outside onUpdate() and never ever caused a crash.

There was no error output, just once I managed to catch one saying that the problem is a NullPointerException in World.java on line 507. Surprisingly, there I found the following:

public boolean isLocked()
    {
        return jniIsLocked( addr );
    }

Could someone tell me what could be going on? I even went so far as to destroy the bodies one at a time:

if (!destroyList.isEmpty()){
    Body b = destroyList.get(0);
    destroyList.remove(0);
    mPhysicsWorld.destroyBody(b);
}

The problem persists though.

Notes: The object I am destroying is made of several bodies connected by WeldJoints to one central body. The bodies overlap, so I use negative groupIndex to prevent them from colliding with each other. Removing all the joints associated with a particular body before removing it does not help. Error output:

05-31 15:32:02.486: W/dalvikvm(927): JNI WARNING: JNI method called with exception raised
05-31 15:32:02.497: W/dalvikvm(927):              in Lcom/badlogic/gdx/physics/box2d/World;.jniStep (JFII)V (CallBooleanMethodV)
05-31 15:32:02.497: W/dalvikvm(927): Pending exception is:
05-31 15:32:02.506: I/dalvikvm(927): Ljava/lang/NullPointerException;:
05-31 15:32:02.526: I/dalvikvm(927):    at com.badlogic.gdx.physics.box2d.World.contactFilter(World.java:507)
05-31 15:32:02.526: I/dalvikvm(927):    at com.badlogic.gdx.physics.box2d.World.jniStep(Native Method)
05-31 15:32:02.536: I/dalvikvm(927):    at com.badlogic.gdx.physics.box2d.World.step(World.java:298)
...

Solution

  • I think you have to first remove the physics connector also and you have to do all this thing into the update method. So, the remove sequence is 1. Remove joints from the body 2. Remove physics connector 3. Destroy body from the world and other necessary thing you have to manage manually that I was not mentioned.

    EDIT : I found another thing for you. You have to implement runnable handler to destroy body and joints. The following code work for me where I saw how to delete body.

    dRunnableHandler.postRunnable(new Runnable() {
            @Override
            public void run() {
    
                // destroy the bullet body
                PhysicsConnector physicsConnector = gameObject
                        .getPhysicsWorld().getPhysicsConnectorManager()
                        .findPhysicsConnectorByShape(Bullet.this);
                gameObject.getPhysicsWorld().unregisterPhysicsConnector(
                        physicsConnector);
    
                gameObject.getPhysicsWorld().destroyBody(bulletBody);
                particleSystem.setParticlesSpawnEnabled(false);
    
                gameObject.getEngine().getScene().detachChild(Bullet.this);
    
                gameObject.removeBulletCounter++;
            }
        });