# [SOLVED] rotating a transform by 90° then wait 1 second before next rotation

Hello good people,

I’ve managed to code myself blind on this one…
I’m trying to rotate a transform by 90° everytime i press a button but I want to make it so that if the button remains pressed, the transform will first lerp toward the next 90°, then wait a second or so, then rotate an extra iteration.

So far I have :

``````void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
{
Rotate90();
}
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, 10 * smooth * Time.deltaTime);

//here i call a simple IEnumerator to WaitForSecondsRealtime(1);
}

public void Rotate90()
{
targetRotation *= Quaternion.AngleAxis(90, Vector3.back);
}
``````

Two main issues:

• while the key is pressed, the object will continue to spin.
• the object will not stop at a 90° position when the use stops pressing the key.
What am I missing here? Thanks!

A quick and easy way of doing that would be using a bool and coroutine, like so;

``````public class RotateTransform : MonoBehaviour
{
[SerializeField]
private float _rotationTime = 2f;
[SerializeField]
private float _delayBetweenRotations = 1f;

private WaitForSeconds _rotationDelay;
private Quaternion _targetRot;

private bool _rotating;

private void Start()
{
_rotationDelay = new WaitForSeconds(_delayBetweenRotations);
_targetRot = transform.localRotation;
}

private void Update()
{
if(Input.GetKey(KeyCode.RightArrow) && !_rotating)
{
_rotating = true;

StartCoroutine(Rotate(_rotationTime));
}
}

private IEnumerator Rotate(float rotateTime)
{
var startRot = transform.localRotation;
_targetRot *= Quaternion.AngleAxis(90, Vector3.back);

var time = 0f;

while (time <= 1f)
{
transform.localRotation = Quaternion.Lerp(startRot, _targetRot, time);
time += Time.deltaTime / rotateTime;
yield return null;
}

transform.localRotation = _targetRot;

yield return _rotationDelay;

_rotating = false;
}
}
``````

Instead of GetKey() use GetKeyDown(). The latter fires only in the Frame that the key was pressed, the former in all Frames where the key is down.

Your call to the coroutine will have no effect since it will NOT stop execution of the main thread, it will return immediately (the coroutine will then wait a second, and Exit after one second). What you can do is set a booean canAcceptKeypress and set it to false when you rotate, and then, in the coroutine, after it waited one second, reset canAcceptKeypress to true. Use the same Coroutine to lerp the Rotation.

Excellent, thank you so much, i’ve learned a lot trying to understand the method you used and implementing it to my build. Works exactly as I wanted, thanks again!!

Thanks for the reply!

I did try GetKeyDown initially but could only get 1 single rotation out of it so the user had to tap the button/key each time instead of holding it…

Note that starting coroutine each time is actually very inefficient.
Timer approach in Update could be easier to implement and have less GC alloc impact on the performance:

``````// Something like
private bool _keyPressed;
private float _timer;

// in Update
if (Input.GetKeyDown(...)) {
_keyPressed = true;
}

if (Input.GetKey(...)) {
Rotate();
} else {
_keyPressed = false;
_timer = 0;
}

// Then in rotate:
private void Rotate(){
_timer += Time.deltaTime;
if (_timer >= 1f) {
// Do an actual rotate
_timer = 0;
}
}
``````

Coroutines don’t generate garbage unless you generate garbage inside them.

``````    public sealed class CoroutineGarbage : MonoBehaviour
{
private void Start()
{
for (int i = 0; i < 10000; ++i)
StartCoroutine(EmptyCoroutine());
}

private System.Collections.IEnumerator EmptyCoroutine()
{
int index = 0;

while(true)
{
index += 1;

yield return null;
}

}
}
``````

Running coroutines do not. Starting coroutine will.
Try starting a coroutine each frame, you’ll see the difference.