Is there a worldUp parameter in the Quaternion.Lerp function?

Hi,
I need to smooth rotate a cube through all the axes and i am using Quaterning.Lerp to do so.
A “simple” issue that i found is when i rotate the cube through just one axis and does not exeed a certain angle.
I read on internet that i should not read the transform.rotation.eulerAngle Vector3 because i could get wrong values since the unity angle motor is the Quaterion and not the Euler angles.

Vector3 target_rotation;
float angle_rotation;

public void Start() {
   angle_rotation = 20;
}

public void updateRotation() {
    target_rotation.x = transform.rotation.eulerAngles.x;
    target_rotation.y = transform.rotation.eulerAngles.y;
    target_rotation.z = transform.rotation.eulerAngles.z;

    target_rotation.x -= angle_rotation;
}

public Update() {
    transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(target_rotation), Time.deltaTime * 3.85f);
}

Here there’s my basic code, where i would like to smooth rotate my cube through just the X axis and the issue is that the cube does not want to look up with the forward direction to the sky (the up world direction) or to the ground with the up direction. The cube refuses to rotate and instead rotates back and get stuck in a “loop” rotation.
I think the code must be tried to understand, anyway i would like (as the code says) that the cube rotates with an angle rotation of 20 each time the updateRotation() will be called, but the cube does not exeed 90 degrees of rotation and go back, any clue?

The title of this thread asks if there is a worldUp parameter (internally i mean) in the Quaternion.Lerp function because this error seems like when i use the LookAt() function to look at an object, and through a worldUp paramenter of the function, i can say which direction of the object must look at the sky.

Thanks in advance to solve this problem, hope it is something relativelt easy.

1 Like

Well…

  1. your code won’t run, there is a syntax error in it (your Update method does not have a return type).

  2. What is the point of ‘updateRotation’? You never call it. Also, in that function you grab the x,y,z… why not just set ‘target_rotation = transform.rotation.eulerAngles’?

  3. What is your expected behaviour?

Also, no, Quaternion.Lerp doesn’t have an up vector internally. Quaternion.Lerp interpolates a quaternion along the shortest linear path from a to b.

Also, don’t use Euler angles the way you use them here. You’re asking for trouble.

You are right it won’t not run cause i’ve written the most important part of the code without checking the syntax.

Anyway I have another script that calls periodically the ‘updateRotation’ function, like every second, and the ‘updateRotation’ function sets the target_rotation.

For example, as in this script is shown, i want the cube smoothly rotates about 20 degrees each second, but when the forward direction look at the world up direction it does not rotate anymore and get “stuck”.

Actually i don’t want to ask for touble… I just found a way to simply do what i should do, but as i am seeing is no longer the simplest way…
I do not really know how to do what i should do anymore, if continuing in this way with lerp and using these Quaterion methods or just change the functions and logic, like using transform.Rotate() and stuff like that, but those functions won’t rotate my cube smoothly, that’s the problem

Happy Valentine’s Day

OK, this makes sense.

This is called gimbal lock. The x axis and y axis have overlapped and the change in rotation is undefined.

Here is a video on gimbal lock:

https://www.youtube.com/watch?v=zc8b2Jo7mno

This is why euler angles are said to be avoided all together.

The problem wasn’t becuase you use Quaternion. The problem was because you used euler to calculate your quaternion.

Here’s how you’d accomplish it with ONLY quaternions. Note I tossed in an invokerepeating call that updated every 1 second like you described:

    Quaternion target_rotation;
    float angle_rotation;

    public void Start()
    {
        angle_rotation = 20;
        this.InvokeRepeating("InvokeEverySecond", 0f, 1f);
    }

    public void updateRotation()
    {
//this is like subtracting 20 degrees from the x component of euler angles, but with out the gimbal lock issue
        target_rotation = transform.rotation * Quaternion.AngleAxis(-angle_rotation, Vector3.right);
    }

    public void Update()
    {
        transform.rotation = Quaternion.Lerp(transform.rotation, target_rotation, Time.deltaTime * 3.85f);
    }


    private void InvokeEverySecond()
    {
        updateRotation();
    }

This is pretty close to the solution I was going to post. – Edited out some code that wasn’t necessary

Thank you so much. It took too much time to rewrite the thousand of code i wrote for the game, thank you.
Now it works wisely and smoothly and i didn’t know gimbal lock could be so annoying, so thank you for the notice and experience, i will keep in mind!:slight_smile: