StartCoroutine works once

Hi!

having a problem with StartCoroutine, it seems like it works only once.

the purpose of the code is to show 3…2…1… and then start the game after the player clicked resume (which is after he paused the game previously obviously) .

my code

    if (resume.paused || restart.continueGame1)
    {
        StartCoroutine(smoothBack());

        if (continueGame)
        { 
            Time.timeScale = 1f;
            resume.paused = false;
            restart.continueGame1 = false;
            continueGame = false;

        }

IEnumerator smoothBack()
{

    Time.timeScale = scale;
    three.SetActive(true);

    yield return new WaitForSeconds( scale);

    three.SetActive(false);

    two.SetActive(true);

    yield return new WaitForSeconds( scale);
    two.SetActive(false);

    one.SetActive(true);

    yield return new WaitForSeconds( scale);
    one.SetActive(false);

    continueGame = true;

}

for the first time everything runs great,
but when I try to run the" smoothBack() " for the second time and beyond it doesn’t work.

need your help!
thanks!

Your issue is line 7 in your first code snippet:

Time.timeScale = 1f;

When you call StartCoroutine your coroutine will immediately run up to the first yield statement before the StartCoroutine call returns. That means your coroutine has already set Time.timeScale to “scale”. However when you come back and “continueGame” is true you set the Time.timeScale back to 1. Since you probably intended to set the timeScale to some very small (not 0) number that means each of the WaitForSeconds will only wait for one frame since you set the timescale back to 1.

Just remove that line and you should be fine. Though the coroutine should set the timeScale back to 1 at the end.

You don’t seem to need your "continueGame " bool at all. It look like you assumed that StartCoroutine will somehow “wait” until the coroutine is finished. That’s not true. The code after your StartCoroutine call runs immediately after the coroutine hits the first yield. That’s why your first call kind of worked. It never entered the if statement. However you started a new coroutine every frame. Your code of starting the coroutine should look like this:

if (resume.paused || restart.continueGame1)
{
    resume.paused = false; // ensures we only start the Coroutine once
    restart.continueGame1 = false;  // ensures we only start the Coroutine once
    StartCoroutine(smoothBack());
}

And at the end of your coroutine you should set the timescale back to 1

    // [ ... ]
    yield return new WaitForSeconds( scale);
    one.SetActive(false);
    Time.timeScale = 1f;
}

Though instead of using that “tiny scale trick” you can now simply use WaitForSecondsRealtime. This does also work when the timescale is set to “0”.