In the example below, how can I get FinishFirst() to complete first before running DoLast(), while still retaining the ‘public void StartPage()’ signature?
I’m trying to avoid making “StartPage()” return an IEnumerator as that would force me to change it in the interface. It would be great if my Interface for StartPage() supported both IEnumerator and Void without needing to implement both.
I know this is an old question but the popular answer is wrong. It’s using two Coroutines, DoLast is constantly checking to see if FinishFirst is done, and even then there’ll be up to a 100ms delay after FinishFirst completes before DoLast is called.
Why not just call DoLast at the end of FinishFirst? If you don’t know what method will need to be called at the end, you can pass it as an Action parameter:
public void StartPage() {
print("in StartPage()");
StartCoroutine(FinishFirst(5.0f, DoLast));
}
IEnumerator FinishFirst(float waitTime, Action doLast) {
print("in FinishFirst");
yield return new WaitForSeconds(waitTime);
print("leave FinishFirst");
doLast();
}
void DoLast() {
print("do after everything is finished");
print("done");
}
You could either call DoLast() after the yield in the FinishFirst function or you could make DoLast a coroutine too with a loop that yields while the FinishFirst coroutine is running.
Much late, but if you want to check if a coroutine had finished or not instead of waiting and then run the next code sequentially, other than the obvious way of declaring an additional boolean flag you can use setup the IEnumerator type variable instead of doing StartCoroutine( on the method directly. (Which is the same, since the method returns IEnumerator.
This variable is useful for StopCoroutine, but if you set that variable to null at the end of the coroutine it can doubles as a way to check if a coroutine ended or not by null checking it.
I use this so players cannot input while the story is advancing. For example, defines :
//this check is necessary for the first time or StopCoroutine will stop to nothing, resulting in a run time error
if(advanceStoryDelayRoutine != null)
{
StopCoroutine(advanceStoryDelayRoutine);
}
advanceStoryDelayRoutine = AdvanceStoryDelayRoutine();
StartCoroutine(advanceStoryDelayRoutine);
And then the input code can check against this variable
Here’s a simple extension class I wrote that adds a callback to UnityWebRequest.Send.
public static class NetworkingUtils
{
public static void Send(this UnityWebRequest request, MonoBehaviour behavior, Action onFinished)
{
behavior.StartCoroutine(routine(request,onFinished));
}
private static IEnumerator routine(UnityWebRequest request, Action onFinished)
{
yield return request.Send();
if (request.isError)
Debug.LogError(request);
else
{
Debug.Log("Results for " + request + ":
" + request.downloadHandler.text);
onFinished();
}
}
}
Then you can use it by passing an action in to Send that will get called on completion. You’ll also need to stick in a Monobehaviour so the coroutine works.
request.Send(monoBehavior, ()=>print("Done"));
You’ll probably want to modify it to do more with errors (a different callback perhaps).