Character Controller Crouching and Events

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Alic
Posts: 39
Joined: Fri Jul 29, 2011 2:25 pm

Character Controller Crouching and Events

Post by Alic »

Hey Norbo, you miracle worker you.

The Character Controller's capsule fires its InitialCollisionDetected event when it goes into crouch stance with objects it was already in contact with, without CollisionEnded being fired first. So for example, the InitialCollisionDetected gets fired when the character first comes into contact with a floor, but then it fires again when the character crouches, without CollisionEnded ever firing.

I'm guessing this has to do with setting the character's capsule height, but is there any way to get more consistent behavior from this, so a new InitialCollisionDetected will only be fired after CollisionEnded has been called?

Thanks a lot.
Alic
Posts: 39
Joined: Fri Jul 29, 2011 2:25 pm

Re: Character Controller Crouching and Events

Post by Alic »

After a bit more investigation, I think what is happening is that the InitialCollisionDetected Event is being fired a second time and then CollisionEnded is being fired immediately after, as part of the same frame. So the collision which is ending must be the original one, and the Ended event just fires after the Detected event if they happened in the same frame, as they do when the capsule is resized (just guessing here, of course). Is it important that the events fire in this order? Or... Is there any way to keep the same contacts while changing the size of the capsule? (I'm guessing not).



*edit*

Also, one workaround seems to be to use the immediate CollisionEnding event in combination with the InitialCollisionDetected event. That makes it so the ending event fires before the second collision detected event.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Character Controller Crouching and Events

Post by Norbo »

I believe your analysis is correct. Deferred events are dispatched in an 'order' which isn't generally ideal. Instead of being purely chronological, they are dispatched by object event hook order and, for single objects dispatching more than one event type, there is a fixed type order.
Is it important that the events fire in this order?
That particular order is not particularly important; swapping the type orders would be trivial. Maintaining a strictly chronological order for deferred events is a little trickier though.
Or... Is there any way to keep the same contacts while changing the size of the capsule? (I'm guessing not).
By removing the call to ClearContacts, yes- but you may not like the consequences :) For example- upon crouching, a contact that was on the character head and is no longer near the body of the character may continue to exist and block the character from progressing.
Also, one workaround seems to be to use the immediate CollisionEnding event in combination with the InitialCollisionDetected event. That makes it so the ending event fires before the second collision detected event.
Using immediate events to capture the true order of execution is indeed the best option here. Mixing a deferred and immediate event will produce other ordering issues, though. Using a DetectingInitialCollision with CollisionEnding should avoid it entirely at the cost of dealing with asynchronous access in the event handlers.

[Digression: Events, and in particular deferred events, are some of my most hated features in the engine. Their current implementation forms an unmaintainable mess of crisscrossing cobwebs. If there's another big redesign, expect collision pair management and event handling to change significantly- deferred events would likely be removed entirely in favor of some convenience methods to 'manually' defer events from immediate handlers.]
Post Reply