Get collision.impulse without OnCollisionEnter

Hello everyone!
I have some trouble with this situation:
Let’s suppose I have a long pillar on the ground, then it’s hitted by a cannon ball, and so it falls. I would need to get the impulse collision when it hits the ground.
I cannot use OnCollisionEnter, because the pillar was hitting the ground from the start.
So, I was trying to recreate the code of collision.impulse. In order to be sure I don’t make any mistakes, I tried to test it during an actual collision, but It seems my actual code is incorrect

private void OnCollisionEnter(Collision collision)
    {

        Rigidbody CollisionBody = collision.rigidbody;
        if (CollisionBody != null)
        {
            Vector3 MyPreviousVelocity = MyPreviousVelocityTracker.PreviousVelocity;
            Vector3 CollisionPreviousVelocity = collision.gameObject.GetComponent<PreviousVelocityTracker>().PreviousVelocity;

            Debug.Log("impulse: " + collision.impulse);
            Debug.Log("Maybe impulse: " + ((MyBody.mass * (MyBody.velocity - MyPreviousVelocity)
                + (CollisionBody.velocity - CollisionPreviousVelocity) * CollisionBody.mass)));
              
            Debug.Log("My DiffMomentum: " + (MyBody.mass * (MyBody.velocity - MyPreviousVelocity)));
            Debug.Log("ItsDiffMomentum: " + (CollisionBody.velocity - CollisionPreviousVelocity) * CollisionBody.mass);   
           
        }
       

    }

where

public class PreviousVelocityTracker : MonoBehaviour
{
    [HideInInspector]
    public Vector3 PreviousVelocity;
    [HideInInspector]
    public bool StopTracking;

    private Rigidbody MyBody;

    private void Awake()
    {
        MyBody = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        if (!StopTracking) PreviousVelocity = MyBody.velocity;
    }
}

if collision.impulse is “the total impulse applied to this contact pair to resolve the collision” I thought I could get it by the sum of the difference of the momentum of the two objects in two consecutive fixedframes, but the result I get is very different:

Output example:
impulse: (-4.1, 0.0, 0.0)
Maybe impulse: (-1.9, 0.3, -1.4)
My DiffMomentum: (2.2, 0.3, 0.4)
ItsDiffMomentum: (-4.1, 0.0, -1.8)

I noticed that most of time the impulse is very similar to “ItsDiffMomentum”, sometimes is similar to “My DiffMomentum”, rarely is completely different from both and almost never is similar to “Maybe impulse”.

Can anyone help me?

Thank you a lot! ^^

Best way would probably be a way around the problem - what are you trying to archive? Why do you need the impulse?

“Maybe impulse” is clearly incorrect - think of two objects moving in the same direction, touching slightly because the object behind the other one is slightly faster - you would add their forces and get a huge impulse force, when the actual impulse is extremly small.

“My DiffMomentum” seems quite right, I guess but you also have to account for the CollisionBody and it’s mass.
So if you kind of sum it up with “ItsDiffMomentum” maybe you could get the right value.

Docs about Collision.impulse:

"
Description
The total impulse applied to this contact pair to resolve the collision.

The total impulse is obtained by summing up impulses applied at all contact points in this collision pair. To work out the total force applied you can divide the total impulse by the last frame’s fixedDeltaTime.
"

contact pair - so you need both bodies with their velocities and masses in one calculation AFAIK.
I tried solving this for quite a long time until I realized that there was a better solution to my problem than actually calculating those forces.

Btw when you try to combine their velocities in one calculation, think about the following case:
One object is basically falling down - the other object is moving completely horizontal against the falling one.
If you just substract the velocityA from velocityB you basically turn the falling ones velocity into an upward force and therefor get a higher impulse than the actual applied forces.

So you only care for forces/velocities which actually affect the impulse, basically projecting them on the vector (objectA.transform.position-objectB.transform.position) (if their transform position is at their center of mass - but thats still just a vague guess on the actual applied forces, because you’d have to use the contact points to get a real solution - as you said, you can’t use “OnCollisionEnter” theres no way you’d get them.)

One more: if you just want to seperate the objects, you can use ComputePenetration .

I am working on a game about physically destructible buildings during the development, I had to write my own physics engine which results in a hybrid system with unitys physics - to get to the point: To archive “soft collisions” (preventing the building from behaving completely rigid, because it isn’t, it can crumble into parts) I use invisible colliders to collect all the collision data I need and then reset the position (to a predicted position, respecting the previousVelocity and previousAngularVelocity combined with the amount of the impulse I want to apply)
And then, at the end of the frame, updating all the visuals (based on their disconnected, invisible collider GameObects)

Edit: this seems way more complicated than it actually is.

Use OnCollisionStay then.

1 Like

Thank you for your help. Just one thing: you wrote ““My DiffMomentum” seems quite right, I guess but you also have to account for the CollisionBody and it’s mass.
So if you kind of sum it up with “ItsDiffMomentum” maybe you could get the right value.” but my “Maybe impulse” was exactly that sum.

[quote=“Edy, post:3, topic: 801101, username:Edy”]
Use OnCollisionStay then.
[/quote] ehm o_______o
No, ok, really, thank you so much!
I didn’t know the existence of this method, Google really didn’t help me to find it in all my researches for this problem.
It perfectly works for what I needed, so thank you again!

Now I am just a bit curious about how Unity calculates collision.impulse, since my attempts didn’t give the correct result, but my issue is certainly resolved.

1 Like

It’s the sum of the individual impulses at the contact points that compose the collision. As result, collision.impulse has an informative meaning, but not a physical utility.

The underlying physics engine, PhysX, exposes the individual impulses at every contact point. That would be useful, as those are the impulses and positions actually applied by the engine to resolve the collision. However, those are not exposed in Unity. I’ve requested Unity to expose them, but the average waiting time for this kind of feature requests is ~5 years (yes, seriously :().

It’s the point 4 in this post:
https://discussions.unity.com/t/721805

1 Like

Oh, interesting. Thank you very much for the explanation!

1 Like