Search code examples
unity-game-engine

Is there a way to change from -180 to 180 to 0 to 360 rotation


So I haven't noticed this until now but Unity's rotation goes from -180 to 180 when altering it through script. I fount this pretty weird considering the rotation, when altered in the inspector, can go up to infinity, but that is probably for some reason which I am not aware yet. Why is this an issue to me? Well I am trying to rotate an object from its current rotation back to 0 and it should be a counter clockwise rotation. Everything works when I am working with rotations up to 180 degrees, anything above that and my rotation code just doesn't work, basically I can't make the object rotate more than half a circle. I feel like I would be able to code this a lot easier with the more standard and traditional 0 to 360 rotations. Any feedback is appreciated, thanks in advance.

Edit: Sorry for the late response, here is the code:

[ContextMenu("Rotate Chamber")]
public void RotateChamber()
{
    StartCoroutine(RotateOverTime(60, 1f, true));
}

[ContextMenu("Reload Chamber")]
public void Reload()
{
    float currentAngle = -chamber.localEulerAngles.z;
    StartCoroutine(RotateOverTime(currentAngle, 5f, false));
}

private IEnumerator RotateOverTime(float angle, float duration, bool clockWiseRotation)
{
    Quaternion startRotation = chamber.localRotation;
    Quaternion targetRotation = chamber.localRotation * Quaternion.Euler(0, 0, clockWiseRotation ? -angle : angle);

    float elapsedTime = 0f;
    while (elapsedTime < duration)
    {
        chamber.localRotation = Quaternion.Lerp(startRotation, targetRotation, elapsedTime / duration);
        elapsedTime += Time.deltaTime;
        yield return null;
    }

    chamber.localRotation = targetRotation;
}

I don't know how much it will help since this isn't some advanced code it is pretty basic stuff, but thanks for the help anyway.


Solution

  • The method you are looking for is Transform.RotateAround.

    The issue with approach you took lies in the way Quaternion works - it represents the shortest path one vector can take to become another vector (or at least that's the way I like to explain it to myself). So, rotating by more then 180 degree is pointless - since rotation by 185 degree is essentially also a rotation by 175 degree in the other direction.

    What you could do instead would be calling RotateAround with a speed until you get the angle that interests you. So, divide angle by duration- that's the rotation you are interested in per second (multiply by Time.deltaTime). As to the axis - I assume you want to rotate around Transform.forward?

    private IEnumerator RotateOverTime(float angle, float duration, bool clockWiseRotation)
    {
        float speed = angle / duration * (clockWiseRotation ? 1.0f : -1.0f);
    
        float elapsedTime = 0f;
        while (elapsedTime < duration)
        {
            chamber.RotateAround(chamber.position, chamber.forward, speed * Time.deltaTime);
            elapsedTime += Time.deltaTime;
            yield return null;
        }
    }
    
    

    Not sure about the axis, I assume you rotate a revolver chamber so rotation around it's forward vector makes sense.