Unfortunately, it seems to me the current collision events (or their handlers) OnCollisionStay, OnCollisionEnter and OnCollisionExit are insufficient, even for detecting accurately if you are grounded or not. I’m new to Unity, but I write the following with the understanding I’ve gained after various tests and by reading the documentation (ambiguous in many parts).
For example, if you have a character with rigidbody standing on a static box collider (the ground), you would maybe expect the OnCollisionStay to only be called after the character has been moved by the physics update according to its current velocity. However, this is NOT the case (at least in Unity 2.6.1f3 which I’m using). The OnCollisionStay is called also if in the beginning of the physics update a “collision” is detected, and if so, then that handler is NOT called again, if a collision happens after the move. The event OnCollisionExit works similarly (it’s like the negation of the OnCollisionStay but it is not raised if a collision between the same colliders were not detected last time), so if you were colliding the ground before the physics update, the collision events cannot tell you if you are colliding it after the physics update.
In another words, you get to know about collision exits with a lag of one fixed update/physics update. Also, if you are out of a collision for only 1 physics frame, there seems to be no way to detect that with the collision handlers (also onCollisionEnter is useless here).
So when implementing the FixedUpdate, if you are really still grounded and jump by only updating the y-velocity, not y-position, a simple implementation using onCollisionStay will regard you as grounded also at the beginning of the next FixedUpdate, so you will have full ground control and maybe possibility to jump again. If you double jump and you add a constant to the y-velocity to implement the jumping, you will jump with double the y-velocity increase you intended. You could force you to be always regarded as airborne after a jump, but the delay remains when you exit a collision without jumping (e.g. run off a platform).
Another confusing thing is that when you are in a collision handler and reading the transform.position, it seems the character with the rigidbody has always finished the physics update. In another words, the handling of the collision events are delayed until the physics update has finished.
That’s why comparing the y-coordinate of contact points with the transform.position.y (plus some constant) does NOT work (as fast implementation) when trying to find out if you are colliding a collider you can stand on. Instead, you are forced to use the normals.
I understand that current collision events fit well in some cases where you directly change the Transform.position in the FixedUpdate function. However, In my opinion, the collision event interface needs to be improved so that Unity users can easily create even higher quality game physics.