Stabilize hovercraft rigidbody upright using torque

Viewed 1821

I'm currently creating a game involving a hover-bike. when the bike collides with something , it's angles change naturally. I wish to create some sort of way for it to tend back to 0. Here's what I've tried:

if (hoverbike.rotation.x != 0 || hoverbike.rotation.z != 0)
        {
            hoverbike.AddTorque(x: Mathf.MoveTowardsAngle(hoverbike.rotation.x, 0, 0.01f), y: hoverbike.rotation.y, z: Mathf.MoveTowardsAngle(hoverbike.rotation.z, 0, 0.01f));
        }

        transform.Rotate(0.0f, -Input.GetAxis("Mouse X") * 0.5f, 0.0f);

It's hard to explain what it's doing because I don't understand what it's doing, it just seems to spin out. Here's the rest of my code if interested: https://pastebin.com/kzMDQMVF, it's a mess but I'm still learning how to use Unity.

Oh and angle y shouldn't tend to 0 because that's the horizontal angle.

1 Answers

You can determine the quaternion that would rotate the hovercraft from its current up to world up using Quaternion.FromToRotation:

Rigidbody hoverRB; // hovercraft's rigidbody

Quaternion deltaQuat = Quaternion.FromToRotation(hoverRB.transform.up, Vector3.up);

Then use Quaternion.ToAngleAxis to convert that to an angle & axis:

Vector3 axis;
float angle
deltaQuat.ToAngleAxis(out angle, out axis);

Then, cancel out some of any existing rotational velocity so that you'll eventually reach the goal:

float dampenFactor = 0.8f; // this value requires tuning
hoverRB.AddTorque(-hoverRB.angularVelocity * dampenFactor, ForceMode.Acceleration);

And then apply some torque along the axis we found before, scaled by how much angle remains:

float adjustFactor = 0.5f; // this value requires tuning
hoverRB.AddTorque(axis.normalized * angle * adjustFactor, ForceMode.Acceleration);

Any conversion between radians Rigidbody uses and degrees of ToAngleAxis is redundant with the float constants, so don't worry too much about it.

Make sure this is all being done in FixedUpdate (or a function called/running in FixedUpdate time) due to how the torque's direction will likely need to change from one physics step to another. So, altogether:

Rigidbody hoverRB; // hovercraft's rigidbody

...

void FixedUpdate() 
{    
    Quaternion deltaQuat = Quaternion.FromToRotation(hoverRB.transform.up, Vector3.up);

    Vector3 axis;
    float angle
    deltaQuat.ToAngleAxis(out angle, out axis);

    float dampenFactor = 0.8f; // this value requires tuning
    hoverRB.AddTorque(-hoverRB.angularVelocity * dampenFactor, ForceMode.Acceleration);

    float adjustFactor = 0.5f; // this value requires tuning
    hoverRB.AddTorque(axis.normalized * angle * adjustFactor, ForceMode.Acceleration);
}
Related