Problem with rotation in code, I think it's because of local angles?

I think I need a separate set of eyes on this to see if I’m missing something.

I have a script that when a user clicks on an object, it will animate from one angle to another angle. In the inspector, you can input the Euler angles for the start and end rotations as a Vector3, then the code converts that to a Quaternion.Euler();

For this, I have an object that I want to start at 90° on the X axis, and end at 0°. When I click on it, it rotates from 90³ to 180° instead. I’m not sure why. Can someone take a look and show me what I’m doing wrong?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClickRotate : MonoBehaviour
{

    [Tooltip("Start rotation value for the object.")]
    public Vector3 startRotation;
    [Tooltip("End rotation value for the object.")]
    public Vector3 endRotation;
    [Tooltip("Speed to roate the object.")]
    public float rotationSpeed = 2f;

    private bool _onEndRotation = false;
    private Quaternion startRot;
    private Quaternion endRot;
    private bool doRotation = false;
    private float slerpPerc = 0f;

    // Start is called before the first frame update
    void Start()
    {
        startRot = Quaternion.Euler(startRotation);
        endRot = Quaternion.Euler(endRotation);

        this.transform.rotation = startRot;
    }

    // Update is called once per frame
    void Update()
    {
        if(doRotation)
        {
            slerpPerc = Mathf.MoveTowards(slerpPerc, 1f, Time.deltaTime * rotationSpeed);

            if (_onEndRotation)
            {
                transform.rotation = Quaternion.Slerp(endRot, startRot, slerpPerc);
            }
            else
            {
                transform.rotation = Quaternion.Slerp(startRot, endRot, slerpPerc);
            }

            if(slerpPerc >= 1f)
            {
                slerpPerc = 0f;
                doRotation = false;
                _onEndRotation = !_onEndRotation;
            }
        }
    }

    private void OnMouseUp()
    {
       doRotation = true; 
    }
}

Slerps and euler are worst enemies.
Maybe have 2 gameobjects with the proper rotation and cache the variables of those in start? So you can read the actual quaternions?

Yikes that would be a ton of work. There are hundreds of things that need this code in the scene, that’s why I wanted to do a script. I’ve been told Quanternion is the way to go with rotation, so trying to do that, but I need to be able to input the angle.

If you want a rotation to work in angular space, change the rotational angle there, not with a Quaternion.Slerp/Lerp

Each frame generate a new angle from the updated quantity:

MyGameObject.transform.rotation = Quaternion.Euler( 0, 0, currentAngle);

For smooth transitions, this always works in all cases and is only one line of code:

Smoothing movement between any two particular values:

You have currentQuantity and desiredQuantity.

  • only set desiredQuantity
  • the code always moves currentQuantity towards desiredQuantity
  • read currentQuantity for the smoothed value

Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

The code: SmoothMovement.cs · GitHub

Since you’re dealing with angles, pay attention to the suggestion on line 68 in the above gist.

Another approach would be to use a tweening package line LeanTween, DOTween or iTween.

1 Like

Ahhhh but if I add game objects through code and delete them when I get the rotations, it works, so thanks :slight_smile:

1 Like