Pausing and Resuming infinite loops?

Is there’s a way to pause and then resume a loop? i have this code, it runs the loop then i use Break once the player hits a criteria and trigger an event, now after that i’m trying to resume the loop (by adding a trigger to resume loop on NextArea Coroutine), and i don’t know how to go about it! any suggestion is appreciated, thanks!

    IEnumerator SpawnWaves () //Spawns waves
    {
        yield return new WaitForSeconds (startWait);
        while (true)
        {
        for (int i = 0; i < WavesCount; i++) {
            GameObject Enemy = Enemies [Random.Range (0, Enemies.Length)];
            Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z); //spawn positions
            Quaternion spawnRotation = Quaternion.identity;
            GameObject newhaz = Instantiate (Enemy, spawnPosition, spawnRotation); //spawns the Enemy
            newhaz.GetComponent<Rigidbody> ().velocity = newhaz.transform.forward * EnemySpeed;
        }
            yield return new WaitForSeconds (waveWait);
            EnemySpeed = EnemySpeed + -0.5f; //Speed increase after every wave
            EnemyCount = EnemyCount + 1;

            if (gameOver == true) {
                break;
            }
            else if (EnemySpeed == 35) { //when speed of enemy reaches this, stops spawning enemies
                StartCoroutine (ActivateShotsMsg ());
                Clock.SetActive (false);
  

                StartCoroutine (NextArea ());
                break;
            }
        }
    }

Would resuming be different than simply restarting the coroutine?

This method feels really messy to me, which may be the source of your difficulty here.

Ideally, a function should serve a single purpose, which should be evident by the name of your function. So if the method is called “SpawnWave”, it should do that and only that. Yours looks like it’s doing a pause, spawning and initializing the enemy units, checking for game state conditions, and loading other areas.

My initial thoughts are that it would be better to run a method every time an enemy is killed that checks to see if there are any more enemies left. You also seem to be using Coroutines just to get the benefit of the WaitForSeconds, which is unnecessary. Just use Invoke if you want to call something after a certain amount of time.

This is more or less pseudocode using some of what you have, but should clarify what I’m trying to say:

private int currentWave = 0;
private int maxWave = 10;
private float waveDelay = 3f;
private float newAreaDelay = 5f;

private float enemySpeed = 1f;
private int enemyCount = 10;

public List<Enemy> enemies = new List<Enemy>();

void EnemyKilled(Enemy enemy) {
    enemies.Remove(enemy);

    if (enemies.Count() == 0) {
        if (currentWave < maxWave) {
            Invoke(StartWave, waveDelay);
        } else {
            Invoke(NextArea, newAreaDelay);
        }
    }
}

void StartWave() {
    currentWave += 1;
    enemySpeed += .5f;
    enemyCount += 1;

    for (int i = 0; i < enemyCount; i += 1) {
        SpawnEnemy();
    }
}

void SpawnEnemy() {
    Enemy newEnemy = Enemies[Random.Range (0, Enemies.Length)];
    Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    GameObject newhaz = Instantiate(Enemy, spawnPosition, Quaternion.identity);
    newhaz.GetComponent<Rigidbody>().velocity = newhaz.transform.forward * enemySpeed;
    enemies.Add(newEnemy);
}

Obviously you’ll also need a component on the player object to detect if it’s been killed to activate the GameOver state.

3 Likes