Crash on PostSolve, removing body from World

Topics: Developer Forum
Nov 8, 2010 at 5:54 PM
Edited Nov 8, 2010 at 7:50 PM

Idea is that when an object lands on the player and the force is greater than X, character loses health. Works fine in terms of calculating the force of impact, but if I try to remove the Body from the World, I get a crash:

 

 
private void PostSolve(ContactConstraint contactConstraint)
        {
            float maxImpulse = 0;

            for (int i = 0; i < contactConstraint.Manifold.PointCount; ++i)
            {
                maxImpulse = Math.Max(maxImpulse, contactConstraint.Manifold.Points[i].NormalImpulse);
            }

            if (maxImpulse >= deathOnImpactSize)
            {
              _world.RemoveBody(_fixture.Body);
            }
        }

 

 

I'm assuming it's because somehow I'm trying to remove a Body that's been removed, even though technically I've just removed it and it no longer exists? So PostSolve is being called multiple times?

If I call_world.RemoveBody(_fixture.Body); at level startup (ie just once) it works fine. How can I limit the call to remove that fixture just once?

I've run some more tests, and confirmed that there's no crash if I call RemoveBody multiple times outside of PostSolve (by holding down a button, for example).

EDIT also, it looks like it's crashing out here, in World.cs 

Debug.Assert(!IsLocked);

Which makes sense. What's locked, here? And why is it locked?

Nov 8, 2010 at 8:01 PM
Edited Nov 8, 2010 at 8:02 PM

Aha. Looks like RemoveBody is locked during callbacks.

In case this helps anyone else, what I've done is simply to set a flag in my object (bDestroy) to true on impact - then from the object's Update method I can safely destroy the body (and the object) if (bDestroy) {destroy();}

 

public void destroy()
        {
            // completely remove this object
            _levelManager.physicsObjects.Remove(this);
            _world.RemoveBody(_fixture.Body);           
        }

 

:)

 

If anyone's got a more sensible solution to this, I'd love to hear it.

Nov 8, 2010 at 11:54 PM

I do the same thing as thezombiecow in my game engine.

Another possible solution is to add all the bodies you want to destroy to a list, and then after the world has updated you loop through that list and remove them all.

Coordinator
Nov 9, 2010 at 4:31 PM

That is what we did automatically in FPE 2.x (with the lists). I think I will implement it again on both add and remove.

Nov 25, 2010 at 8:04 PM

Will you also implement it on Body.Active?

I think it has the same "problem"

Coordinator
Nov 25, 2010 at 8:05 PM

I've already implemented it in changeset 79890

It will be a part of FPE 3.2.