Home > Back-end >  Making an endless wave spawner that spawns harder enemies over time in Unity
Making an endless wave spawner that spawns harder enemies over time in Unity

Time:02-22

I copied Brackey's tutorial in order to make an enemy spawner for my fps game, but something I am struggling with is making it so that over time new enemy variants spawn, and they have they're own locations. I think I understand how I could make more of one enemy type spawn over time, but how could I make it so that each enemy kind has they're own spawning amounts and locations?

Here is my code:

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 int count;
        public float rate;
    }
    public Wave[] waves;
    int nextWave = 0;

    public Transform[] spawnPoints;

    public float timeBetweenWaves = 5f;
    float waveCountDown;

    float searchCountDown = 1f;

    SpawnState state = SpawnState.COUNTING;

    void Start()
    {
        waveCountDown = timeBetweenWaves;
        if (spawnPoints.Length == 0)
        {
            Debug.LogError("You forgot to put in spawnpoint, idiots");
        }
    }

    void Update ()
    {

        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()
    {
        Debug.Log("Wave Completed");

        state = SpawnState.COUNTING;
        waveCountDown = timeBetweenWaves;

        if (nextWave   1 > waves.Length - 1)
        {
            // Implemnt some sorta multiplier here to make it harder over time
            nextWave = 0;
            Debug.Log("ALL WAVES COMPLETE! Looping...");
        }
        else
        {
            nextWave  ;
        }

        

    }

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

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

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

        state = SpawnState.WAITING;

        yield break;
    }

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

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

Should I just make a new wavespawner script for each new enemy type? I'm considering it but I imagine that would be quite taxing. Any help would be appreciated, thank you.

CodePudding user response:

You can create different scriptable objects for different enemies and set values for them like this:

[CreateAssetMenu(fileName = "Enemy", menuName = "Enemy")]
public class EnemyData : ScriptableObject
{
    public int Health;
    public int Damage;
    public List<Transform> SpawnPoints;
}

then, create different enemy prefabs and set each enemy a data:

public class Enemy : Monobehavior
{
    public EnemyData data;
}

and set enemy on each wave:

[System.Serializable]
public class Wave
{
    public string name;
    public Enemy[] enemy;
    public int count;
    public float rate;
}

then on spawn function, instead of using your spawn points, use spawn points in data object:

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

    Transform _sp = _enemy.SpawnPoints[ Random.Range (0, _enemy.SpawnPoints.Length) ];
    Instantiate (_enemy, _sp.position, _sp.rotation);
}

I hope this brings an idea for you.

  • Related