DEV_LOGS / PHYSICS_ENGINE_V0.4
C# UNITY

Collision Resolution:
Impulse Method

By Aryan S. Published 2 days ago 4 min read
A B

FIG 1.0: IMPULSE VECTORS ALONG COLLISION NORMAL

Earlier versions of my physics engine used a penalty-based method for collisions. While simple to implement (pushing objects apart based on overlap depth), it resulted in "spongy" interactions where objects would sink into each other before bouncing back.

To fix this, I refactored the solver to use Impulse Resolution. Instead of correcting position directly over time, we calculate an instantaneous change in velocity.

The Math

The magnitude of the impulse scalar $j$ is calculated using the coefficient of restitution $e$ (bounciness) and the relative velocity along the normal.

j = -(1 + e) ċ (vrel ċ n) mA-1 + mB-1

Implementation Details

Here is the simplified C# implementation used in the solver loop. Note that we calculate inverse mass upfront to avoid division during the physics step.

PhysicsSolver.cs
public void ResolveCollision(Body a, Body b, Contact contact) {
    // 1. Calculate relative velocity
    Vector2 relativeVel = b.Velocity - a.Velocity;

    // 2. Calculate velocity along normal
    float velAlongNormal = Vector2.Dot(relativeVel, contact.Normal);

    // Do not resolve if velocities are separating
    if (velAlongNormal > 0) return;

    // 3. Calculate impulse scalar
    float e = Mathf.Min(a.Restitution, b.Restitution);
    float j = -(1 + e) * velAlongNormal;
    j /= a.InvMass + b.InvMass;

    // 4. Apply impulse
    Vector2 impulse = j * contact.Normal;
    a.Velocity -= a.InvMass * impulse;
    b.Velocity += b.InvMass * impulse;
}

Results & Next Steps

The new system handles stacks of boxes much better. However, there is still some jitter when objects are resting on the ground due to micro-bounces.