Reputation: 2891
I have a coroutine like so:
private IEnumerator ShortFlashes()
{
this.startedShortFlashes = true;
this.finishedShortFlashes = false;
const int maxFlashes = 3;
int numFlashesSoFar = 1;
if (numFlashesSoFar > maxFlashes)
{
Debug.Log("All 3 short flashes finished!");
this.finishedShortFlashes = true;
yield break;
}
while (numFlashesSoFar <= maxFlashes)
{
yield return new WaitForSecondsRealtime(0.05f);
this.Renderer.enabled = true;
yield return new WaitForSecondsRealtime(0.05f);
this.Renderer.enabled = false;
Debug.Log("Number of short flashes so far: " + numFlashesSoFar);
numFlashesSoFar++;
}
}
When this coroutine is running, I can see messages in the Unity console enumerating the number of short flashes, just as intended. (Debug.Log("Number of short flashes so far: " + numFlashesSoFar);
).
However, Debug.Log("All 3 short flashes finished!");
is never executed, even when numFlashesSoFar
exceeds maxFlashes
.
This is very inconvenient, because in my Update()
method, there are some additional actions that I would like to perform if this.finishedShortFlashes
is true
.
How can I fix this issue?
Upvotes: 0
Views: 298
Reputation: 13783
You've hardcoded the values.
const int maxFlashes = 3;
int numFlashesSoFar = 1;
if (numFlashesSoFar > maxFlashes)
{
//...
}
if (numFlashesSoFar > maxFlashes)
is effectively equal to if (1 > 3)
, which is never true.
I genuinely don't understand why you structured the code the way you did, which makes it hard for me to understand the core issue here.
This makes much more sense:
const int maxFlashes = 3;
int numFlashesSoFar = 1;
while (numFlashesSoFar <= maxFlashes)
{
yield return new WaitForSecondsRealtime(0.05f);
this.Renderer.enabled = true;
yield return new WaitForSecondsRealtime(0.05f);
this.Renderer.enabled = false;
Debug.Log("Number of short flashes so far: " + numFlashesSoFar);
numFlashesSoFar++;
}
Debug.Log("All 3 short flashes finished!");
this.finishedShortFlashes = true;
Note that you don't need the if
. When the while
loop finishes, you already know that the condition is met (otherwise the while
loop would not have finished yet.
I don't understand the purpose of the yield break;
in your code. It seems unnecessary, so I removed it.
Upvotes: 4
Reputation: 3574
I don't understand why you put that if-statement above the loop. The while loop will continue until the while-statement is false. There is no need for the if-statement, you can simply put the code you have inside your if-statement below the loop:
private IEnumerator ShortFlashes()
{
this.startedShortFlashes = true;
this.finishedShortFlashes = false;
const int maxFlashes = 3;
int numFlashesSoFar = 1;
while (numFlashesSoFar <= maxFlashes)
{
yield return new WaitForSecondsRealtime(0.05f);
this.Renderer.enabled = true;
yield return new WaitForSecondsRealtime(0.05f);
this.Renderer.enabled = false;
Debug.Log("Number of short flashes so far: " + numFlashesSoFar);
numFlashesSoFar++;
}
Debug.Log("All 3 short flashes finished!");
this.finishedShortFlashes = true;
}
Also, you can see yield return
in a Coroutine as a "temporary break in code", because it waits for the next frame to continue the code. Unless you return a WaitForSeconds of course, then it will wait until the given amount of time has passed.
Upvotes: 0
Reputation: 3634
I think you're missing the point of yield
keyword.
Once the execution encounter yield return
the execution is transferred back to the calling method and the execution state for the routine is retained. The next time you call that same routine, the execution resumes from where it has been yielded.
More information is available in the official documentation
In that particular case, the line Debug.Log("All 3 short flashes finished!");
is never hit, because when the control steps into the method initially, the numFlashesSoFar
variable is set to 1 so the condition is never met. Then it goes into the loop, where the yield
keyword is encountered. So the next time, the execution continues from within the loop.
Upvotes: 0