kredj
kredj

Reputation: 255

unity fix orientation in an axis

I have a first person rigidbody capsule that rotates so that he will always be upright against the gravity direction. I want to rotate my player to the side so that the player camera will not rotate vertically.

My code is,

void Update() {
    FixOrientation();
}

void FixOrientation()
{
    if (trans.up != -GetGravityDirection())
    {
        Quaternion targetRotation = Quaternion.FromToRotation(trans.up, -GetGravityDirection()) * trans.localRotation;
        trans.localRotation = Quaternion.RotateTowards(trans.localRotation, targetRotation, 5f);
    }
}

The result is, current

In the image above, I changed the gravity direction to point to the ceiling.

This code only rotates the player at the global x-axis no matter where he is facing which means when i'm facing global forward or backward, the player will rotate vertically the camera. What I want is for it to rotate on the side(local z axis).

Upvotes: 0

Views: 621

Answers (1)

derHugo
derHugo

Reputation: 90683

Unity already has a method for exactly that: Transform.Rotate has an overload taking an angle and a rotation axis.

It might look like

// rotation speed in degrees per second
public float RotationSpeed;

void Update()
{
    FixOrientation();
}

void FixOrientation()
{
    if (transform.up != -GetGravityDirection())
    {
        // Get the current angle between the up axis and your negative gravity vector
        var difference = Vector3.Angle(transform.up, -GetGravityDirection());

        // This simply assures you don't overshoot and rotate more than required 
        // to avoid a back-forward loop
        // also use Time.deltaTime for a frame-independent rotation speed
        var maxStep = Mathf.Min(difference, RotationSpeed * Time.deltaTime);

        // you only want ot rotate around local Z axis
        // Space.Self makes sure you use the local axis
        transform.Rotate(0, 0, maxStep, Space.Self);
        }
    }

A Sidenote:

Just in general be careful with the direct comparison of two Vectors

trans.up != -GetGravityDirection()

uses an approximation of 0.00001. In your case that should be fine anyway but for comparing you should rather use

Vector3.Angle(vector1, vector2) > threshold

to define a wider or stronger threshold

Upvotes: 1

Related Questions