Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Bug EstimatedImpulse is wrong

Discussion in 'Physics for ECS' started by CookieStealer2, Nov 10, 2021.

  1. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    119
    I did some experiments with collision event impulse. The setup: My capsule character runs into a static vertical wall head on with ~12 m/s speed. I can get the delta velocity of the collision by dividing the collision impulse with the mass of the character. I would expect the total delta velocity of the collision to be around 12 m/s. The problem is that CollisionEvent.Details.EstimatedImpulse does not match that.

    My observations of EstimatedImpulse:
    Most of the time the delta velocity calculated from EstimatedImpulse at each frame will match the current speed of the character. This is true even when the collision lasts more than one frame! This does not make sense, since in that case the collision should end after one frame. Other times it will be greater than the current speed. This means that the total delta velocity for a collision that last several frames always will be too high.

    My observations of SolverImpulse:
    There is also another impulse value in the collision event data: CollisionEventData.SolverImpulse. This value seems to always add up to the expected amount after each collision, but it is internal.

    So my questions are:
    Why is SolverImpulse internal?
    What does SolverImpulse and EstimatedImpulse represent?
    And what's their difference?

    Example collision:
    2 frames long.
    Frame 1:
    • CharacterSpeed = 11.86 (Before collision)
    • deltaV (EstimatedImpulse) = 21.95 (Why is this greater than character speed?)
    • deltaV (SolverImpulse) = 1.36
    Frame 2:
    • CharacterSpeed = 10.63
    • deltaV (EstimatedImpulse) = 10.27
    • deltaV (SolverImpulse) = 10.08
    Summed impulses after collision:
    • deltaV (EstimatedImpulse) = 32.22 (Wrong)
    • deltaV (SolverImpulse) = 11.44 (OK, Close enough to speed before collision)
     
  2. Sab_Rango

    Sab_Rango

    Joined:
    Aug 30, 2019
    Posts:
    121
    I don't know the engine structure api. Yet I believe that 2 times high value "EstimatedImpulse" is value of J impulse

    which is came from equation J impulse equal to
    link https://www.myphysicslab.com/engine2D/collision-en.html#resting_contact
    infinite mass vs a rigidbody impulse equation

    j = (−(1 + e) vap1 · n)/(1⁄ma + (rap × n)2 ⁄ Ia)

    e= elasticity if 1 fully elastic.

    And estimated value of J impulse when Rigidbody collides with static object it would be about 2mv, which is about 22 kg*m/sek in your case.
     
  3. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    119
    My character and wall has 0 restitution, so e should be 0 right? So the equation would be just mv. Besides, I've also seen higher values of 34 m/s deltaV from EstimatedImpulse.
     
  4. Sab_Rango

    Sab_Rango

    Joined:
    Aug 30, 2019
    Posts:
    121
    hmm, maybe it is coming from jacobian solver. When object penetrates deeply during collition detection, it will be solved by adding extra impulse to the rigidbody.

    edit 1: If there is enough relative velocity, there will not be any impulse by Jacobian solver.
    Yet if the relative velocity is smaller than a specific threshold there will be additional impulse (e.g during stacking objects)
     
    Last edited: Nov 11, 2021
  5. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    119
    Maybe, but then there must be another impulse applied in the opposite direction to stop the character from moving away from the wall. Hmm, maybe the impulse in frame 2 is actually in the other direction? 21.95 - 10.27 = 11.69 I need to investigate further...
     
  6. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    119
    Nope that's not it, it was just a coincidence. Although I realized that the impulse comes from different collider keys in some cases. For example this collision:

    2 frames long.
    Frame 1:
    • CharacterSpeed = 11.61 (Before collision)
    • collider key X, deltaV (EstimatedImpulse) = 5.66
    • collider key Y, deltaV (EstimatedImpulse) = 10.60
    Frame 2:
    • CharacterSpeed = 5.00
    • collider key X, deltaV (EstimatedImpulse) = 4.94
    During first frame two collider keys are hit, then the next frame only the first collider key is hit.
    I still don't get how these deltaV end up canceling my speed.
     
  7. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    119
    Ok, I think I understand what is happening now and I'm pretty sure this is a bug.

    The idea behind EstimatedImpulse seems to be "the total impulse applied for the whole collision". It is essentially a prediction of what the total impulse will be after you sum up SolverImpulse for all frames of the collision. Unity calculates EstimatedImpulse by considering the remaining velocity after solver impulse is applied. The remining velocity will be canceled in the next couple frames, thus a prediction of the impulse can be calculated by multiplying the remaining velocity with the mass. So, EstimatedImpulse = SolverImpulse + predicted impulse.

    The bug is that the predicted impulse will be calculated for each collider key. If you hit two collider keys during a frame the predicted impulse will be doubled, if three it will be tripled and so on... I think the user expects that you can sum all EstimatedImpulse coming from same entity to get total impulse. But this not not the case if the predictedImpulse is not zero. If you only ever collide with one collider key everything will be fine, and I guess that is how the bug went unnoticed.

    Attached is some more data on collisions with multiple collider keys, to help the Unity/Havok engineers understand and fix the bug.
     

    Attached Files:

    Last edited: Nov 12, 2021
    steveeHavok likes this.
  8. MaxAbernethy

    MaxAbernethy

    Joined:
    Mar 16, 2019
    Posts:
    53
    Hello, I'm not familiar with the EstimatedImpulse implementation but I have done a similar thing in the past, which worked as you describe and had the same problem.

    One way to do better would be to actually solve all of the contact points for the next step's displacement. You could reuse code from the Unity Physics contact solver to do it, though it might be difficult finding the pieces you need and adapting them. It might be a bit expensive as well.

    Another thing you could try would be to use Unity.Physics.SimplexSolver. That should be easier and cheaper, but also less accurate since it doesn't handle rotation at all. You mentioned a character though, and often those don't rotate, so the simplex solver should do pretty well. Hope that's some help to you.