Page 1 of 1

Removing object after collision

Posted: Sat Sep 11, 2010 11:28 pm
by Brad_Mclain
Hi

I am trying to remove an entity after collision with any other object I have added an event hook and am I trying to remove the entity from the space in the handler.

The code I used to do this is something like the following:

Code: Select all

space.add(rocketBox);
rocketBox.eventManager.addEventHook(new EventHandlerInitialCollisionDetected(rocketCollision));

private void rocketCollision(Entity sender, Entity other, CollisionPair collisionPair)
{
         space.remove(sender);
}
This works most of the time however occasionally I get the error: Cannot remove entity from this space as it belongs to a different or no space.

Any idea on what is going wrong?

Thanks,

Brad

Re: Removing object after collision

Posted: Sun Sep 12, 2010 1:38 am
by Norbo
More than one collision can be detected in one frame, so this can happen occasionally.

In the deferred case (InitialCollisionDetected is a 'deferred' event), the events are run at the end of the frame, so removing an entity won't stop the following one from running. You could just check to see if the entity you're trying to remove belongs to the space first by checking its space property.

Note that removing entities in event handlers should be done with care. Removing an entity directly from an Immediate event is not supported (the Immediate handlers are called from the internal multithreaded context, and trying to remove an entity would deadlock with the update thread). Removing entities in deferred events works better, but it's still possible to cause problems if an event triggers other events (a "collision was modified" InvalidOperationException can occur if it's the same event type as the one currently running).

If you run into those kind of issues, one option is to buffer the addition of the entity until after the update is finished. I'd like to make this area less fragile in an upcoming version.

Re: Removing object after collision

Posted: Sun Sep 12, 2010 3:24 am
by Brad_Mclain
Thanks doing the check before removal fixed up the problem.

Maybe adding a way (if it doesn't already exist) to tag entities for deletion at the end of the space update cycle?

Re: Removing object after collision

Posted: Sun Sep 12, 2010 4:16 am
by Norbo
Most likely part of the solution will be some kind of built-in convenience buffering that lets you queue up items to be included/removed at the beginning of the next frame (or end of the current), like Space.BufferedAdd and Space.BufferedRemove. This would be pretty helpful for asynchronous updating too, since the current Space.Add locks the space's update system to prevent it from going while adding.

The other part of the solution will be to make the event dispatching system itself less vulnerable, or at least make failures more obvious.

Re: Removing object after collision

Posted: Sat Mar 26, 2011 6:39 pm
by RayBatts
Can I see a code example for this for the new codebase? I can't find the examples anymore : ( I'm trying to create an event for Entity.CollisionInformation.Events.InitialCollisionDetected += //Don't know what kind of function to add here.

Re: Removing object after collision

Posted: Sat Mar 26, 2011 8:00 pm
by Norbo
The documentation can be found on codeplex: http://bepuphysics.codeplex.com/wikipag ... umentation

The BEPUphysicsDemos project source can be downloaded with the whole BEPUphysics solution from the repository: http://bepuphysics.codeplex.com/SourceC ... changesets

The FishInABarrelDemo.cs is still in there, using the InitialCollisionDetected/CollisionEnded events.

For InitialCollisionDetected specifically, the type of delegate it wants is InitialCollisionDetectedEventHandler<T>(T sender, Collidable other, CollidablePairHandler pair). For an entity's collidable, T will be EntityCollidable. The BEPUphysics.Collidables.Events namespace contains the delegate types for collision events.