How to properly wait/pause in C#

I really need to figure out the proper way to wait for a coroutine to finish completely before continuing. It also has to be called from a regular method that returns void. If your wondering why it has to be called from a method returning void, it appears methods that are “invoked” cannot be of type IEnumerator.

So I am at a loss as to how to solve this problem. Can anyone help?

This code

using UnityEngine;
using System.Collections;
 
public class WaitTest : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
 
        Debug.Log("Before callPause");
 
        StartCoroutine(callPause(2f));
 
        Debug.Log("After callPause");
 
 
    }
 
    IEnumerator callPause (float seconds) {
 
        Debug.Log("Before call to pause");
        yield return StartCoroutine(pause(seconds));
        Debug.Log("After call to pause");
 
    }
 
    IEnumerator pause (float seconds) {
        Debug.Log("Before yield in pause");
        yield return new WaitForSeconds (seconds);
        Debug.Log("After yield in pause");
 
    }
 
 
    // Update is called once per frame
    void Update () {
 
    }
}

Produces these results

So far so good until the next one shows up out of order…

It should be @ the end

iByte

Your Start function does not yield the StartCoroutine function, so after starting up the callPause function, it immediately continues. To get your desired result, add yield return before the StartCoroutine in Start and make it return IEnumerator instead of void.

HI Tom,

thanks for the reply.

I have had no success in try to start a IEnumerator function with invoke.

I am wondering is this a bug or working as designed?

iByte

Your original code is correct but it doesn’t do what you might expect.

In C#, you can’t make any of the standard callback functions (Start, OnCollisionEnter, etc) into coroutines like you can in JS. You can only start other coroutines from these functions. What happens is that the StartCoroutine inside Start returns like a normal function and execution continues immediately on the next line (ie, the Start function itself doesn’t get paused by the WaitForSeconds call). You need to ensure all delayed action takes place in the coroutines themselves since the Start function can only trigger them off.

1 Like

This really isn’t true, at least not for Start. I program C# exclusively and use Start as Coroutine all the time. As long as you make sure it’s defined as IEnumerator Start instead of void Start, it works.

Hi Tom, yes you are correct but I think andeeee meant start as it defaults in a new C# script file (and as I had it defined in my exampe).

Don’t misunderstand andeeee’s point. The start callback or any for that matter which is being overwritten by the developer shouldn’t have any delay (exceptions: Update, FixedUpdate). These need to complete execution so that the next phase or event can continue in running your games start up, physics, draw calls, read mouse events etc.

Keep your sleeps inside the coroutines. IEnumerator Start () is just like creating a regular function, like making IEnumerator Nobody (), or int Start() as you are not actually overriding the void Start () callback…

tomoprime, if your not overriding void Start() then how exactly does IEnumerator Start () or int Start () get called … just wondering???

I did not misunderstand andeee (who I know is a great help on these forums), but he is incorrect and so are you. An IEnumerator Start is called by Unity just like the default void Start. Try it. Create a C# Monobehaviour, add a single function IEnumerator Start(). Add a yield WaitForSeconds (which andeee claims shouldn’t work) and a Debug.Log after it. The start will get called by Unity as a normal Start function and it will run as a Coroutine, properly executing the yield and everything after it, just like it would when you’d have a yield in a JS Start function. There is nothing wrong with doing this. In fact, it is the easiest way to implement an initialization ordering.

Unity uses reflection to identify and call the Start function, and is apparently smart enough to start it as a Coroutine when it discovers the return value is IEnumerator. It won’t wait for it to complete though, so it cannot be used to delay the Update function, for instance.

Actually it’s best explained here… Though I haven’t tested to see the differences between Javascript / C#.

use System.Threading.Thread.Sleep(timeInMilliseconds);
where timeInMilliseconds is the time you want to wait in milliseconds (write 1000 to wait a second)!

Note that you’ll need to add “using System;” to the top of your file