Coroutine Exits while loop, although condition is still met

Viewed 45

I have a coroutine function written for Unity which is as below:

IEnumerator initialize_reference_att()
{
    Quaternion zero = new Quaternion(0, 0, 0, 0);
    while (Input.gyro.attitude == zero)
        Debug.Log("This line is required otherwise exits while without looping");
        yield return null;

    reference_attitude = Input.gyro.attitude;
    Debug.Log("Reference attitude set to " + reference_attitude);
    yield return null;
}

In this way it works as expected however when I write the while loop as below:

while (Input.gyro.attitude == zero)
    yield return null;

the execution of while loop ends although Input.gyro.attitude == zero condition is still true. Apparently it has something to do with returning from coroutine immediately after while loop without doing any other thing. Because when I add an debug log line(as in the first code snippet), it works as expected. Does anybody have any idea why it behaves in that way? My issue is solved but I only want to understand why it happens. Thanks everyone.

1 Answers

This is basically the good old missing curly braces story:

while (Input.gyro.attitude == zero)
    Debug.Log("This line is required otherwise exits while without looping");
    yield return null;
    

basically equals writing

while (Input.gyro.attitude == zero)
    Debug.Log("This line is required otherwise exits while without looping");

yield return null;

=> without the { } for enclosing a scope the while only applies to the first following expression after it


what you want is

while (Input.gyro.attitude == zero)
{
    Debug.Log("This line is required otherwise exits while without looping");
    yield return null;
}

Because when I add an debug log line(as in the first code snippet), it works as expected.

Let me doubt that. Your first snippet is an endless loop that the way it is written should crash your entire app as soon as the condition is true once.

In contrary actually I would expect

while (Input.gyro.attitude == zero)
    yield return null;

which basically equals

while (Input.gyro.attitude == zero)
{
    yield return null;
}

or also simply

yield return new WaitWhile(() => Input.gyro.attitude == zero);

would allow to yield once a frame => continue in the next frame and check again. Except something happened we all waited for and Unity suddenly made the API multi-threading ready you would always get the same value for Input.gyro.attitude during the same frame

Related