Reputation: 31
I have a question about coroutine behaviour in case of loops, see following code extract as example done on a Unity C# script:
void Start() {
StartCoroutine(FSM());
}
IEnumerator FSM() {
state="State1";
while (true) {
Debug.Log("State "+state);
yield return StartCoroutine(state);
}
}
IEnumerator State1() {
while (true) {
if (stateTransitionCond) {
state = "NextState";
yield break;
}
yield return null;
}
}
The status machine works fine, but while the current status is Status1 (stateTransitionCond==false
), due to the yield return null
inside the loop of State1()
routine, I was expecting that loop inside FMS()
also performs another iteration generating debug log 'Debug.Log("State "+state);'.
In other words I was expecting a lot of debug log (one for each iteration of State1() routine, when status is Status1) but in the reality only 1 execution is performed while status is Status1.
So I suppose I miss something about yield functionality, is there anybody that can explain me this behaviour?
Upvotes: 2
Views: 9047
Reputation: 1334
Your issue stems from the fact that your code does not break out of the State1()
method until stateTransitionCond == true
.
The method starting the coroutine, FSM()
, is not returned to until State1
is finished. In other words, control flow does not return to the calling method until the coroutine is complete. I believe this is due to the fact that you are yield
-ing State1
inside FSM
(yielding another coroutine). Obviously, "normal" methods do not wait for the coroutine to finish before continuing execution.
Please see the code sample below for an illustrative example:
using UnityEngine;
using System.Collections;
public class CoroutineTest : MonoBehaviour {
// current FSM state
public string state = "";
void Start()
{
StartCoroutine(FSM());
}
IEnumerator FSM()
{
state = "State1";
while (true)
{
Debug.Log("State: " + state);
// ExecuteOnce will execute exactly once before returning to the outer function
yield return StartCoroutine(ExecuteOnce());
// ExecuteIndefinitely will execute indefinitely until its while() loop is broken
// uncomment to test
//yield return StartCoroutine(ExecuteIndefinitely());
}
}
IEnumerator ExecuteOnce()
{
Debug.Log("Calling ExecuteOnce()");
yield return new WaitForSeconds(1f);
}
IEnumerator ExecuteIndefinitely()
{
Debug.Log("Calling ExecuteIndefinitely()");
while (true)
{
Debug.Log("Inside ExecuteIndefinitely()");
yield return new WaitForSeconds(1f);
}
}
}
Upvotes: 2