I have been using Farseer for quite a while now, working on a physics teaching platform project. There are a couple of questions about the engine in my brain that are left unanswered for quite some time, many of which are about collision handling of the engine.
Many people seem to have problems understanding the working of the engine, partly because Farseer lacks a proper API. It might be a good idea for those in the know to confirm the following concepts and KILL any concepts that are wrong.
Collision in Farseer is divided into two stages:
Farseer, using broad phase collision, will find potential collisions in a scene. Said broad phase collision test is done by...
The use a quad tree, which can be found in package "Farseer.Collision".
The class "Farseer.Dynamics.World" has a reference to "Farseer.Collision.QuadTreeBroadphase".
"Farseer.Collision.QuadTreeBroadphase" has a reference to "Farseer.Collision.QuadTree".
Further bounding box test is also done.
If we ever find a need to know which pair(s) of fixtures has the potential to collide, we may do this...
/* Game.Initialize */
public override void Initialize() {
OtherIrrelevantInitCode();
_world.OnBroadphaseCollision += BroadphaseHandler;
base.Initialize();
}
public void BroadphaseHandler(ref FixtureProxy fp1, ref FixtureProxy fp2) {
// code to read about fp1 and fp2
}
But then...
Small question 1
What are some of the common situations that it is useful for us to know which pairs of fixtures are potentially colliding?
Definition of two keywords:
BeforeCollision means two objects are NOT colliding and NOT touching.
OnCollision means two objects are colliding, but touching will NOT fire this event.
AfterCollision means two objects were colliding, but now they are touching only.
OnSeparation means two objects were touching, but now they are not.
Broadphase collision test and precise collision tests are always carried out.
Precise collision may be disabled by returning false in event OnCollision or by using the IgnoreCollision method.
I have heard for more than one time that people say "just leave OnCollision empty and return true". What on earth does that mean? Using the events means that we would like to apply additional effects (e.g. kill an enemy, score, play a sound etc.) when the above events happen.
This answer applies to Farseer Physics 3.3.1 (The current stable version, at time of writing)
Broad-phase is just a performance optimisation. It quickly determines what could collide, so that things that can't collide don't have the more-expensive narrow-phase collision-detection run.
In my experience, the events in Farseer aren't designed as well as they could be. I've found I've had to modify them for my own game - but fortunately this code is actually not too hard to read and modify. Also the documentation isn't accurate in a few places.
BeforeCollision
happens when broad-phase registers a new potential collision, before it creates a Contact
object for the two fixtures. You can block the creation of the Contact
by returning false
in your event handler.
The existence of a Contact
does not necessarily mean that the two fixtures are actually in contact - just that the broad phase succeeded. A Contact
can be touching/not-touching and they can be enabled/disabled (they start out enabled and not-touching).
OnCollision
happens when a Contact
changes from not-touching to touching. You can disable the contact by returning false. Oddly enough, you can re-enable a contact that another event handler disabled on that step if you return true (this is one of the things I changed for my own game).
Only an enabled, touching contact has any effect on the physics simulation.
OnSeparation
is the opposite of OnCollision
: it triggers when the contact changes from touching to not-touching. There's no way to disable/enable a contact here.
AfterCollision
is called for every Contact
that is involved in the physics simulation on that frame (so: those that are enabled, touching, and not in an asleep island). It is called after the the physics simulation step, but before clean-up - most notably before Body.Force
and Body.Torque
are cleared (handy for sound effects and such).
Usually you just use these events to trigger your effects - particles, sounds, game mechanics like destroying objects, and so on. In which case you subscribe to whichever one you want, do whatever you like, and then return true (not disabling/overriding the contact).
It gets a lot more complicated if you want to mess with the physics engine or disable contacts (particularly when you can accidentally re-enable them, with another event handler, as I mentioned earlier). If Farseer's built-in events don't work for you, then it's perfectly reasonable to go into its code and add your own. At this advanced level, it's practically a necessity to be building from source so you can examine exactly what is going on anyway.