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:
Create a physical body for each state when the player is loaded
Save those bodies and their corresponding states in parallel lists
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.