OnCollisionStay contacts are a frame behind.

Hi all,

I need to make some calculations based on collision points with a sphere collider but I'm running into a bit of trouble because the contact.point data from a collision seems to be a frame behind.

I attached a simple script to a sphere collider to demonstrate the issue -

    void OnCollisionStay(Collision collisionInfo)
        // Draw a line from the contact point to the object's current position
        if (collisionInfo.contacts.Length > 0)
            Debug.DrawRay(collisionInfo.contacts[0].point,this.transform.position-collisionInfo.contacts[0].point, Color.cyan );

7032580--833425--Apr-13-2021 11-00-18.gif

As I step through the collision point seems to be a frame behind, but the collider centre from that same sample seems to be in the correct spot.

Am I doing something wrong here? Any help would be great!


I had found something similar with the contact point of the WheelCollider (WheelHit.point). It seems that the engine first runs the collision phase (collisions are collected here), then the integration phase (objects are moved here).

My workaround was to explicitly add the distance offset to the contact point:

collisionPoint += rigidbody.velocity * Time.fixedDeltaTime;

So you get the contact point relative to the object's updated position. I haven't tested this with standard collisions, but works fine with WheelCollider's contact points.


Yes, I assume 3D physics is the same but you’ll get the same in 2D physics (Box2D). This is because the physics system has to create contacts at one stage of the simulation step. If contacts were produced at the end of the step (not done here) then it’ll respond to those in the next step. If contacts are produced at the start of the step then it responds to those during that step which is what you described. In Box2D it looks for new contacts and updates existing ones at the start of the step. It then runs the solver to solve those contacts using impulses and integrate standard velocity movement including gravity, damping etc. This means the contact you see is before it responded/moves so it doesn’t mean it’s currently in contact; it’s historic.

You could of course calculate all current contacts at the end of the step as well as the start but that’s potentially doubling the work.


Hey thanks for the help :) Edy's code seems to be doing the trick :)

1 Like