Search Unity

Question OnCollisionStay contacts are a frame behind.

Discussion in 'Physics' started by petey, Apr 13, 2021.

  1. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    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 -
    Code (CSharp):
    1.     void OnCollisionStay(Collision collisionInfo)
    2.     {
    3.         // Draw a line from the contact point to the object's current position
    4.         if (collisionInfo.contacts.Length > 0)
    5.         {
    6.             Debug.DrawRay(collisionInfo.contacts[0].point,this.transform.position-collisionInfo.contacts[0].point, Color.cyan );
    7.         }
    8.     }
    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!

    Thanks,
    Pete
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,508
    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:
    Code (CSharp):
    1. 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.
     
    petey and MelvMay like this.
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,459
    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.
     
    Edy and petey like this.
  4. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Hey thanks for the help :) Edy's code seems to be doing the trick :)
     
    Edy likes this.