IndexOutOfRangeException on World.Step after enabling/disabling a Farseer physics body?

Posted by WilHall on Game Development See other posts from Game Development or by WilHall
Published on 2012-01-24T17:53:18Z Indexed on 2012/09/06 15:51 UTC
Read the original article Hit count: 178

Earlier, I posted a question asking how to swap fixtures on the fly in a 2D side-scroller using Farseer Physics Engine. The ultimate goal being that the player's physical body changes when the player is in different states (I.e. standing, walking, jumping, etc). After reading this answer, I changed my approach to the following:

  1. Create a physical body for each state when the player is loaded
  2. Save those bodies and their corresponding states in parallel lists
  3. Swap those physical bodies out when the player state changes (which causes an exception, see below)

The following is my function to change states and swap physical bodies:

new protected void SetState(object nState)
{
    //If mBody == null, the player is being loaded for the first time
    if (mBody == null)
    {
        mBody = mBodies[mStates.IndexOf(nState)];
        mBody.Enabled = true;
    }
    else
    {
        //Get the body for the given state
        Body nBody = mBodies[mStates.IndexOf(nState)];

        //Enable the new body
        nBody.Enabled = true;

        //Disable the current body
        mBody.Enabled = false;

        //Copy the current body's attributes to the new one
        nBody.SetTransform(mBody.Position, mBody.Rotation);
        nBody.LinearVelocity = mBody.LinearVelocity;
        nBody.AngularVelocity = mBody.AngularVelocity;

        mBody = nBody;
    }

    base.SetState(nState);
}

Using the above method causes an IndexOutOfRangeException when calling World.Step:

mWorld.Step(Math.Min((float)nGameTime.ElapsedGameTime.TotalSeconds, (1f / 30f)));

I found that the problem is related to changing the .Enabled setting on a body. I tried the above function without setting .Enabled, and there was no error thrown. Turning on the debug views, I saw that the bodies were updating positions/rotations/etc properly when the state was changes, but since they were all enabled, they were just colliding wildly with each other.

Does Enabling/Disabling a body remove it from the world's body list, which then causes the error because the list is shorter than expected?

Update:

For such a straightforward issue, I feel this question has not received enough attention. Has anyone else experienced this? Would anyone try a quick test case? I know this issue can be sidestepped - I.e. by not disabling a body during the simulation - but it seems strange that this issue would exist in the first place, especially when I see no mention of it in the documentation for farseer or box2d. I can't find any cases of the issue online where things are more or less kosher, like in my case. Any leads on this would be helpful.

© Game Development or respective owner

Related posts about c#

Related posts about physics