Home Games About Us Contact Us

Wave Manager - C#

About this project:

The wave manager was my first portfolio entery ever made, hence it's skill level is under other portfolio enteries. The wave manager was made for my first school project, a tower defence game. It uses a custom Wave class defining how many enemies to spawn, at which interval to spawn them, a name for the wave and which enemy to spawn. There are some quoted variables incase the user wants to increase the ammount of enemies spawned.

C#(C-Sharp) +
                
    [System.Serializable]
    public class Wave
    {
        public int ammountOfEnemys;
        //Remove quotes depending on ammount of enemy's
        //public int ammountOfEnemys2;
        //public int ammountOfEnemys3;
    
        public float spawnRate;
    
        public string waveName;
    
        public Transform enemy1;
        //Remove quotes depending on ammount of enemy's
        //public Transform enemy2;
        //public Transform enemy3;
    }
  
    public Wave[] waves;
                
              

The wave manager also has a Enum with 3 States. Spawning, Waiting and Counting. In the Waiting state the Wave Manager checks if there are still enemies left, if yes it returns nothing and if all enemies died it calls the BeginNextWave() function.

C#(C-Sharp) +
                
    public enum SpawnState { Spawning, Waiting, Counting};

    private SpawnState state = SpawnState.Counting;
                  
    void Update()
    {
        if(state == SpawnState.Waiting)
        {
            if(!EnemyIsAlive())
            {
                BeginNextWave();
            }else
            {
                return;
            }
        }
    }
                
              

The EnemyIsAlive() function checks if there are still enemies left alive at a defined interval, if yes then it returns true else it returns false.

C#(C-Sharp) +
                
    bool EnemyIsAlive()
    {
        searchCountdown -= Time.deltaTime;
    
        if (searchCountdown <= 0f)
        {
            searchCountdown = 1f;
          
            //Change "Enemy" if you want to use something different than enemy's
            if(GameObject.FindGameObjectsWithTag("Enemy").Length == 0)
            {
                return false;
            }
        }
      
        return true;
    }
                
              

In the spawning state the Wave Manager runs a SpawnWave(Wave wave) IEnumerator, the spawning state gets activated if the countdown between waves gets to 0 or below. The SpawnWave function holds some code for random events so you can add the possibility to have a stronger wave or something along those lines. The SpawnWave function loops X times where X = ammountOfEnemies to spawn. It then calls the SpawnEnemy() function specified with the enemy to spawn. Then it waits for X ammount of seconds where X = spawnRate defined in the wave class. After it is finished spawning the enemies it returns to the waiting state where it checks if the enemies are dead or not.

C#(C-Sharp) +
                
    // Update is called once per frame
    void Update()
    {
        if(waveCountdown <= 0)
        {
            if(state != SpawnState.Spawning)
            {
                StartCoroutine(SpawnWave(waves[waveIndex]));
            }
        }else
        {
            waveCountdown -= Time.deltaTime;
        }
    }
                
    IEnumerator SpawnWave(Wave wave)
    {
        Debug.Log("Spawning Wave: " + wave.waveName);
        state = SpawnState.Spawning;
      
        //Remove quote if you want random event
        /*
        if (randomEventValue == 2)
        {
            wave.enemy1 = rEEnemy1;
            wave.enemy2 = rEEnemy2;
            wave.enemy3 = rEEnemy3;
        }
        else if (randomEventValue != 2)
        {
            wave.enemy1 = nEnemy1;
            wave.enemy2 = nEnemy2;
            wave.enemy3 = nEnemy3;
        }
        */
      
        for (int i = 0; i < wave.ammountOfEnemys; i++)
        {
            SpawnEnemy(wave.enemy1);
            yield return new WaitForSeconds(1f / wave.spawnRate);
        }

        //Remove quote if you want more than 1 enemy
        /*for(int x = 0; x < wave.ammountOfEnemys2; x++)
        {
            SpawnEnemy(wave.enemy2);
            yield return new WaitForSeconds(1f / wave.spawnRate);
        }
        for(int y = 0; y < wave.ammountOfEnemys3; y++)
        {
            SpawnEnemy(wave.enemy3);
            yield return new WaitForSeconds(1f / wave.spawnRate);
        }*/
      
        state = SpawnState.Waiting;
      
        yield break;
    }
                
              

In the Counting state the Wave Manager increments the current wave by 1 so when the next wave begins the right wave is loaded and it won't reuse the same wave again.

C#(C-Sharp) +
                
    void BeginNextWave()
    {
        Debug.Log("Wave Completed");
    
        //Remove quote if you want random events
        //randomEventValue = Random.Range(0, randomEventPercentage);
    
        //Add code for increasing wave number here if needed
    
        state = SpawnState.Counting;
        waveCountdown = timeBetweenWaves;
    
        if (waveIndex + 1 > waves.Length - 1)
        {
            print("Completed all waves! Insert finish screen or something");
        }
        else
        {
            waveIndex++;
        }
    }
                
              

Conclusion:

As my first portfolio entery I am satisfied with the results, but looking back on it now with the knowledge I have there is so much I could've done better. Perhaps I will update this entery in the future so it matches the level of my other portfolio enteries but for now im keeping it like this. Here is a direct link to the wave manager script in the portfolio repository:

- Wave Manager Github