Hello, my game relies on collision detection but every time I call OnCollisionEnter it’s always a frame too late because OnCollisionEnter is called after FixedUpdate and all the physics simulations. Is there a way around this?
Just in case anyone else is looking along these lines, the short answer is no.
All of the OnCollision*() functions are called after the physics simulation is completed. When OnCollisionEnter() is called, transform.position will already reflect the new location.
The way around it is to manually look for upcoming collisions with your own code.
The further downside to the OnCollision*() functions is that they do not detect a collision in response to the physics simulation. They detect a collision in response to where the object was when it started FixedUpdate().
In other words, if an object is at point A, moves to point B, and collides at point B, the OnCollisionEnter() function will not catch this as a collision because at the start of FixedUpdate() the object was still at point A. This is regardless of anything that took place in the physics simulation, even if the collision is clearly apparent on screen, even if transform.position is clearly in a place where a collision must exist. OnCollision*() will not be called until after the FixedUpdate() (AND after that FixedUpdate()'s following physics simulation) in which the object started in a colliding position.
Which means that the collision at point B will be called after the object has moved to point C. Sounds crazy but that’s how it works. Further discussion here:
To make matters worse, when you use data from the Collision object passed in, that data is also from one FixedUpdate() ago. Collision data and transform data will, at the same time inside any OnCollision*() function, point to an object in 2 different places.
In the physic loop,
FixedUpdate is first called before
But you’ll also notice that
yield return new WaitForFixedUpdate happens right after them, so if required, you might also move your code there.