OnCollision instead of On(Enter)Collision

Topics: Developer Forum
Dec 20, 2010 at 7:59 PM

Hey guys!

Developing a character for a 2D-JnR I'm doing with a hand full of student mates with the Farseer engine (Version 3.0), I reached a point where I just can't find a solution on my own or in this board. Without beating around the bush: I need some kind of OnCollision, which fires every time two physical objects are overlapping. So instead of a OnEnterCollision, like the OnCollision in the Farseer actually is, I need a true OnCollision.. which ignores if the contact it throws is new or old. I can't imagine the Farseer doesn't have something similar.

Example: I have a plain ground and a circle fixture i move around. Fixed rotation for it (for some reasons...). Every single moment the circle is on the ground, I want to calculate the normal to the ground.. but therefore i neet a contact, even if the two bodies didn't seperate.



Dec 20, 2010 at 10:49 PM
Edited Dec 20, 2010 at 10:55 PM

Hi all,

I'm currently porting a game over from Farseer Physics 2.1.3 and I'm facing the same problem.
In previous Farseer versions the OnCollision event kept firing while the two geoms were together, so this represents another important breaking change.

Is there an alternative? If not, I think the old behavior should be restored as it is crucial for some game logic scenarios. Another event should be provided for new contacts, if needed.

A quick example is a character who is at first not reacting (logically) to a physical collision but then changes its state. However, if a collision had already occurred, the new state will be unable to detect it and the reaction will never happen until the objects separate and collide again.



Edit: Actually I just figured out that the AfterCollision event fires continuously as required for this scenario. It doesn't let you cancel the collision however, but may in fact be sufficient for most cases.

Dec 21, 2010 at 2:42 AM

This behavior is not supported as it is implicit in the new behavior. Run your logic as long as the OnSeparation has not been called instead. The new behavior is caused by contacts being cached instead of recreated on each update.

Note that the AfterCollision is only found in the source control at the moment and it is considered unstable.

Dec 21, 2010 at 5:16 AM

Woa, thx for the superfast reaction!! Additionally, we're using version 3.1, not 3.0, as I figured out.

Then I will have a closer look at AfterCollision this evening.

But @ Genbox: So what I did was saving the Contact and fixtureB I got from the latest OnCollision... calculating the normal in every Update of the gameloop, but this didn't work, because if the circle was moved over the ground, I calculated the normal with the OLD contact, instead of the new contact.. but I neet the new contact point. So how can I get this new contact point without a crappy testPoint method? So simple, I want to have the contact point between the two objects at every time.

Dec 21, 2010 at 9:35 AM

Ok, if the AfterCollision event is not recommended and will probably disappear, then the problem still remains.

I agree with Hanno that it is indispensable to have access to the new points over time. If the contacts are now cached between frames, is it possible to have access to this cache?
In other words, if the Fixtures now store a list of their contacts, is it possible to request this list?

The problem with running the logic as long as the OnSeparation has not been called is that it creates a situation where the structure of the physics engine is placing dependencies on the logic of the world entities which may quickly make the logic unwieldy in terms of code organisation and maintenance.

Again, consider changes in the agent's state which are not governed by physical parameters, such as decision-making, timer-based, or other internal (or even external) parameters. The agent then enters a new state which is completely independent from the old but on which it now needs access to the collision information.

It is of course possible to maintain my own cache of collisions at the agent level, inserting contacts when OnCollision fires and removing them when OnSeparation fires, but if Farseer is already doing this anyway, why duplicate the code (and memory)?

Thanks for the fast answer :-)

Dec 21, 2010 at 11:31 AM

The AfterCollision event is only considered unstable at the moment because it is not tested - it will not go anywhere, but might change name at some point.

As for for the cached contacts - You can always get a list of contacts from Body.ContactList (it might change to an array based list instead of doubly linked list at some point) or use World.ContactManager.PreSolve (that is what I do in the debug view) to get your contacts.

The reason I don't recommend you stick a lot of logic into the Fixture delegates, is that they have quite a lot of overhead as they are basically methods being called a lot of times on each update and they can contain huge hunks of code. They are impossible for the compiler to optimize. I put them in there for convenience and an easy way to execute code in small games

No danger in using them, just beware of the side-effects.

Dec 21, 2010 at 12:33 PM

Ah okay, nice idea with the ContactList. So am I right, in this list is every contact since the last new OnCollision happened? Right what I was asking for? (It's the only thing that would make sense to me, but better be too carefull than less ...)

Dec 21, 2010 at 1:22 PM

Cool! This will do fine. I hadn't realized the ContactList was meant to be used like this, but in fact I agree with you it's even better this way :-)

Dec 22, 2010 at 9:20 AM

Did it work, chance?