Rotate quaternion 90 degrees when clicked?

In my game, the player can move and rotate their furniture. The movement has been sorted out, but is there a way to animate a rotation 90 degrees when a mouse button is pressed, preferably through (s)lerp? You can think about how the furniture rotates in the “Animal Crossing” games if you have played any of them, except that the direction does not matter. Thanks in advance!

This is what I currently have:

private void Update()
{
    if (Input.GetMouseButtonDown(1))
    {
        isTurning = true;
    }

    if (isTurning)
    {
        Quaternion currentAngle = transform.rotation;
        Quaternion newAngle = Quaternion.Euler(currentAngle.x, currentAngle.y + 90, currentAngle.z);
        transform.rotation = Quaternion.Lerp(currentAngle, newAngle, Time.deltaTime * 5f);
        if (Quaternion.Angle(currentAngle, newAngle) < 1)
        {
            transform.rotation = Quaternion.Euler(transform.rotation.x, Mathf.Round(transform.rotation.eulerAngles.y / 90) * 90, transform.rotation.z);
            isTurning = false;
        }
    }
}

This seems like a job for coroutines, each coroutine would handle a 90 degree turn, and the upside is that you can have multiple running at the same time.

private void Update()
{
    if (Input.GetMouseButtonDown(1))
    {
        StartCoroutine(RotationCoroutine(0.5f, Quaternion.Euler(0, 90, 0)));
    }
}

private IEnumerator RotationCoroutine(float totalDuration, Quaternion rotationAmount)
{
    float elapsedTime = 0f;
    Quaternion lastRotation = Quaternion.identity;

    while (elapsedTime < totalDuration)
    {
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / totalDuration;

        Quaternion newRotation = Quaternion.Lerp(Quaternion.identity, rotationAmount, percentageComplete);
        transform.rotation *= newRotation * Quaternion.Inverse(lastRotation);

        lastRotation = newRotation;
        yield return null;
    }
}

I believe such an approach should be easier to understand and debug than your current approach. The above snippet will also work when running multiple at the same time!

P.S. You “add” two quaternions together with the * operator.

There is an even more powerful solution, namely tweens, which make the above snippet seem obtuse. Your intended functionality would look like this:

private void Update()
{
    if (Input.GetMouseButtonDown(1) && !isTurning)
    {
        isTurning = true;
        transform.DORotate(new Vector3(0, 90, 0), 0.5f, RotateMode.LocalAxisAdd)
            .OnComplete(() => isTurning = false);
    }
}

You can even use special ease functions or append/simultaneously run a scale up/down tween with virtually no effort at all! :smiley:

You can install a tweening library like DOTween from the asset store.

Hope this helps!