Myk Willis Myk Willis - 1 month ago 18
C# Question

Unexpected control flow in Unity coroutine (detecting completion)

I have a script attached to a Unity 5 GameObject that rotates the object by a fixed amount when a user clicks a button. The rotation is done in a coroutine to allow it to happen smoothly over time.

I want to block the user from performing another rotation of the same object until the first is done. To do this, I've added an

isRotating
boolean that is set to true when the coroutine starts, and to false when the coroutine has completed the rotation. The code is as follows:

using UnityEngine;
using System.Collections;

public class ObjectScript : MonoBehaviour {

private bool isRotating = false;

/* Rotate the object 90 degrees around the x axis centered on the origin */
IEnumerator RotateObject() {
isRotating = true;

var updateRotation = 0.0f; // amount to rotate this tick
for (var totalRotation = 0.0f; totalRotation <= 90.0f; totalRotation += updateRotation) {
updateRotation = 90.0f * (Time.deltaTime / 0.5f);
if (totalRotation + updateRotation > 90.0f) {
updateRotation = 90.0f - totalRotation;
}
transform.RotateAround (Vector3.zero, Vector3.right, updateRotation);
yield return null;
}

isRotating = false; // This line is never reached
}

void Update () {
if (Input.GetKeyDown(KeyCode.X) && !isRotating) {
StartCoroutine (RotateObject());
}
}
}


My issue is that the
isRotating = false
line is never reached, so
isRotating
is left set to
true
, even after the coroutine has finished rotating the object. (I've checked this by placing debug breakpoints on the line, which are never hit). So once the object has been rotated one time, it will never rotate again.

Why does control never get to the line outside of the loop body?

Answer

updateRotation = 90.0f - totalRotation;

=> totalRotation + updateRotation = 90

Every time totalRotation + updateRotation > 90.0f you reassign the updateRotation so that next iteration totalRotation + updateRotation = 90

=> totalRotation <= 90.0f is nerver false