a couple useful Rigidbody extension methods

On a Discord server, I was asked how to do a damped spring torque. As in, you have a world rotation you want your Rigidbody to turn towards. I had just used these old methods I had laying around earlier in the day, so I thought I’d share here as well.

    body.ApplySpringForceToward(targetPosition, spring, damping,
        ForceMode.Acceleration);
    body.ApplySpringTorqueToward(targetRotation, spring, damping,
        ForceMode.Acceleration);

If using ForceMode.Acceleration, a spring of 500 and a damping of 20 gives a slightly jiggly but responsive motion for bodies regardless of mass.

    public static void ApplySpringForceToward(this Rigidbody body,
        Vector3 targetPosition, float strength, float damping,
        ForceMode mode=ForceMode.Force)
    {
        if (body.isKinematic)
            return;

        Vector3 difference = (body.position - targetPosition);
        Vector3 direction = difference.normalized;
        float force = strength * difference.magnitude;
        body.AddForce(-force * direction - body.velocity * damping,
            mode);
    }

    public static void ApplySpringTorqueToward(this Rigidbody body,
        Quaternion targetRotation, float strength, float damping,
        ForceMode mode=ForceMode.Force)
    {
        if (body.isKinematic)
            return;

        Quaternion difference = ShortestRotation(
            targetRotation, body.rotation);

        difference.ToAngleAxis(out float degrees, out Vector3 axis);
        axis.Normalize();

        float radians = degrees * Mathf.Deg2Rad;
        body.AddTorque(
            (axis * radians * strength) - (body.angularVelocity * damping),
            mode);
    }

    public static Quaternion ShortestRotation(Quaternion a, Quaternion b)
    {
        if (Quaternion.Dot(a, b) < 0)
            return a * Quaternion.Inverse(b.Flipped());
        return a * Quaternion.Inverse(b);
    }
3 Likes

That first seconds of the video snippet was all…

public ApplySpringForceToReachLowEarthOrbit()

amirite? :slight_smile:

Have you played with PD filters for this stuff? They’re not a be-all-end-all solution but with good constants they can give really solid single-axis control. I use 'em for the tilty-tilt as well as the yaw on my Jetpack Kurt game.

Unfortunately, it was my boneheaded mistake to “pull object until it aligns” but get the direction of the vector subtraction wrong. Some days, Quaternions are easier than Vectors. Made me laugh though.