Rotate an object's z value to a certain an angle over time then rotate it back to the original angle

Hi, I’m having trouble understanding coroutines and rotation in general.
I’m trying to make a 2D top down sprite attack animation similar to the one in this video…


My goal: when a character inputs an attack key, the sprite would be rotated by a certain angle, pause for a very short time, then rotates back to the exact original angle.

My codes so far:

public float maxTimer = 0.2f;
public float waitTime = 0.1f;

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        StartCoroutine(RotateObject());
    }
}


IEnumerator RotateObject()
{
    float timer = 0f;
    while (timer <= maxTimer)
    {
        transform.Rotate(Vector3.forward * Time.deltaTime * (40/maxTimer));
        timer += Time.deltaTime;
        yield return null;
    }
    yield return new WaitForSeconds(waitTime);
    timer = 0f;
    while (timer <= maxTimer)
    {
        transform.Rotate(Vector3.forward * Time.deltaTime * (-40/maxTimer));
        timer += Time.deltaTime;
        yield return null;
    }
}

Now when I execute this code, the z value would slightly be different every time I hit space instead of returning to the original value of 0 (for example 1.1, -1.3, 0.5, -2.3, etc…). I also think there has to be a cleaner way of doing this. Note that the value 40 in the script is the angle value I want the sprite to be rotated by, and -40 to rotate it back to the original value. Any help would be appreciated!

I bet the reason you are seeing these variations is that you don’t stop when timer == maxTimer, you stop on the first frame that its greater than maxTimer, and with variations on Time.deltaTime the amount of time you rotate forwards is going to differ slightly from the amount of time you rotate back. I personally recommend using Quaternion.Slerp since it will automatically clamp the rotation at the max value (and you will never overshoot). You can try this code out, I have not tested it but I think it will solve the issues you are having.

 IEnumerator RotateObject()
 {
     Quaternion startingRotation = transform.rotation;
     Quaternion targetRotation = startingRotation * Quaternion.Euler(0,0,40);
     float timer = 0f;
     while (timer <= maxTimer)
     {
         timer += Time.deltaTime;
         transform.rotation = Quaternion.Slerp(startingRotation, targetRotation, timer/maxTimer);
         yield return null;
     }
     yield return new WaitForSeconds(waitTime);
     timer = 0f;
     while (timer <= maxTimer)
     {
         timer += Time.deltaTime;
         transform.rotation = Quaternion.Slerp(targetRotation, startingRotation, timer/maxTimer);
         yield return null;
     }
 }