Enemy kill counter and time limit.

I’m making a game where you kill waves of enemies and depending on which you kill the most harder ones spawn in their place, however, there are a few things I’m not sure how to do…


So there are 3 enemy types by default (TypeA, TypeB, TypeC)
-If you kill 3 TypeA, 2 TypeB and 1 TypeC, TypeA is replaced by Type D (A splice of Type 1 and 3)


After each wave, the calculation is done to see which is killed most and least and changes the spawn entities/rates

This is what I have so far:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WaveSpawner : MonoBehaviour
{
    public enum SpawnState { SPAWNING, WAITING, COUNTING };

    [System.Serializable]
    public class Wave
    {
        public string name;
        public Transform enemy;
        public Transform fireEnemy;

        public int enemyCount;
        public float spawnRate;
    }

    public int whichEnemy = 0;
    public Wave[] waves;
    private int nextWave = 0;

    public Transform[] spawnPoints;

    public float timeBetweenWaves = 5f;
    private float waveCountdown;

    private float searchCountdown = 1f;

    private SpawnState state = SpawnState.COUNTING;

    void Start()
    {
        if(spawnPoints.Length == 0)
        {
            Debug.LogError("No Spawn Points Referenced");
        }
        
        waveCountdown = timeBetweenWaves;

    }

    void Update()
    {

        whichEnemy = Random.Range(1,3);

        if(state == SpawnState.WAITING)
        {
            if(!EnemyIsAlive())
            {
                WaveCompleted();
                
            }
            else
            {
                return;
            }
        }

        if (waveCountdown <= 0)
        {
            if (state != SpawnState.SPAWNING)
            {
                StartCoroutine(SpawnWave ( waves[nextWave] ) );
            }
        }
        else
        {
            waveCountdown -= Time.deltaTime;
        }

    }

    void WaveCompleted()  //Add Difficulty Multiplier For More Waves Here
    {

        Debug.Log("Wave Completed!");
        
        state = SpawnState.COUNTING;
        waveCountdown = timeBetweenWaves;

        if(nextWave + 1 > waves.Length - 1)
        {
            nextWave = 0;
            Debug.Log("ALL WAVES COMPLETE! Looping...");
        }
        else
        {
            nextWave++;
        }
    }


    bool EnemyIsAlive()
    {
    searchCountdown -= Time.deltaTime;
    if(searchCountdown <= 0f)
    {
        searchCountdown = 1f;
        if(GameObject.FindGameObjectWithTag ("Enemy") == null)
        {
            return false;
        }
    }
        return true;
    }


    IEnumerator SpawnWave(Wave _wave)
    {
        Debug.Log("Spawning Wave: " + _wave.name);
        state = SpawnState.SPAWNING;

        for (int i = 0; i < _wave.enemyCount; i++)
        {
            SpawnEnemy(_wave.enemy);
            yield return new WaitForSeconds(1f / _wave.spawnRate);
        }

        state = SpawnState.WAITING;
        yield break;
    }



    void SpawnEnemy (Transform _enemy)
    {
        Debug.Log("Spawning Enemy" + _enemy.name);

        if (whichEnemy==1)
        {
            Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)];
            Instantiate(_enemy, _sp.position, _sp.rotation);
        }
        else
        {
            Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)];
            Instantiate(_enemy, _sp.position, _sp.rotation);
        }


        
        
    }

//Anything beyond here was a WIP 

        void EnemiesKilled()
        {
            if(enemyType1.iskilled)
            {
                enemyType1Counter++;
            }

            if(enemyType2.iskilled)
            {
                enemyType2Counter++;
            }

            if(enemyType3.iskilled)
            {
                enemyType3Counter++;
            }
            
        }



        void SpliceEnemies()
        {
            int enemyType1Counter = 0;
            int enemyType2Counter = 0;
            int enemyType3Counter = 0;
            
            if (enemyType1Counter > enemyType2Counter)
            {
                Destroy gameobject.enemyType1;
            }

        }


}

Any help or information would be much appreciated

@DrewWasTaken
Answered this on reddit, and posting the same one here too, incase if you missed that one.

Alright, I saw your code on Unity Questions page, and here are few suggestions from my end, but before that, few questions of my own too.

  1. No offence, but the code looks a little messy, I mean a-lot of the things could be improvised, such as inside an update function, you are calling “whichEnemy” variable and assigning it a random value every-time. You are returning a boolean value with EnemyisAlive function, which in-side, runs to find the “gameobjectwithtag” method, and later this function is called in an update. A thing to keep in mind, update function get’s called every-single frame, it may hamper the performance.

  2. Since you aimed to use different types of enemies, I don’t see any class which has a base level implementation, meaning, if I were you, I could make a base class which will contain all the basic stats such as Type of Enemy, Health, isAlive_Status and much more. and later I could simply inherit the base class to access the base values, since I assume both, enemy as well as your player side may have. “mentioned” common attributes.

  3. Also, line number 130 to 140, what’s the difference in both of these calls? Aren’t they identical to each other?if (whichEnemy==1) { Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)]; Instantiate(_enemy, _sp.position, _sp.rotation); } else { Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)]; Instantiate(_enemy, _sp.position, _sp.rotation); }

  4. Instantiating and destroying game objects, can eat the memory, try object pooling. Some interesting facts about object pooling vs creating/destroying objects. https://forum.unity.com/threads/my-experiments-with-object-pooling-versus-instantiate-destroy.258507/

Anyway, back to your question, In-order to create different enemies, and replacing the next one more harder, you could try defining enum(just like you did with spawnstate) and later, with a simple switch case statement, you could assign/increase the value of it’s health and damage given to player.

P.S. Try using small and more relavent variable names, e.g. you can call, “whichEnemy” as “enemy_type”

Lastly, please don’t get offended, as these are the suggestions. :slight_smile: