# ENEMY SPAWNER - THIS IS A TOUGH ONE

So, I have been trying to think of how to do this for weeks. Can’t figure it out. Here’s what I’m looking at:

My brother and I are making a game that has a few different levels. Each level has a set number of enemy waves, and each wave has a set number of enemies. We wrote out a list of all the enemies and how many are in each wave of each level. We have thought about having them in a certain order and at a certain time, but that seems insane, so for now, just a certain number of each enemy, in a random order.

## Basic Functionality:

Wave 1 of level 1 would always spit out, say, 3 bats and 6 goblins, one at a time, in a random order. Wave 2 would always spit out, say, 5 bats, 14 goblins, and a fire elemental in a random order. So on and so forth.

## Thoughts:

• Since there are multiple levels, each
with their own set of enemies, I
think I would want the spawner to
pull a list of the enemies for each
wave from a script that’s attached to
a game object in each level.
• The spawner would then add up
the total number of enemies for that
wave, and while that number is > 0,
it would spawn an enemy. The hard
part is getting the quantity for each
enemy and only spawning that enemy if
there are some of that enemy left.
• I know the spawner will need a list of all enemy prefabs that it can pull from, and I think the best way would be to use a switch statement. So it will pull a list of all the enemies and put them in a local list, but the part I can’t figure out is the quantity for each enemy. Should I be using a 2D array somehow for the enemy name and quantity? So, the spawner will instantiate a goblin IF… A1 == “goblin” && A2 >= 1?

Anyone have any wisdom on how this can be done!? D:

Thanks for the help in advance!

P.S. I have already made a spawner that randomly spits out enemies until the total enemy count is 0, but doesn’t adhere to any structure, just a random enemy each time until the TOTAL count is 0. This uses coroutines and stuff, so I got the timing and everything down, but if anyone has suggestions on ANY part of this, I’ll take it! Just need to learn a lot still!

So if I understood your problem right you have waves. Each wave will specify how many enemies of each type should be spawned in that wave. You want to only spawn a single enemy at a time. The enemy should be choosen randomly from the available pool of enemies for the current wave.

You haven’t specified how your “list” looks like. I would go with something like this:

``````[System.Serializable]
public class EnemyItem
{
public GameObject prefab;
public int count;
}

[System.Serializable]
public class Wave
{
public List<EnemyItem> enemies;
public List<GameObject> GetWavePool()
{
var res = new List<GameObject>();
foreach(var item in enemies)
{
for(int i = 0; i < item.count; i++)
}
// scramble list
for(int i = 0; i < res.Count-1; i++)
{
var tmp = res*;*
``````

int rnd = Random.Range(i, res.Count);
res = res[rnd];
res[rnd] = tmp;
}
return res;
}
}

public class Spawner : MonoBehaviour
{

IEnumerator Spawning()
{
foreach(var wave in waves)
{
var pool = wave.GetWavePool();
foreach(var prefab in pool)
{
Instantiate(prefab);
yield return new WaitForSeconds(1);
}
}
}
}
So for each wave we simply create a temporary list of all prefabs we want to instantiate. We simply add as many references as required for each enemy / prefab type. Once all elements have been added we simply scramble the list to get a random spawning when iterating through the pool.

This is interesting as I was once encountered the same situation like you and never been able to get back to the game I was making.

I come up with this solution. Check it out

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

[System.Serializable]
public class Enemies{
public GameObject enemyType;
public int count;
}

[System.Serializable]
public class Levels{
public Enemies[] noOfEnemyType;
}

public class LevelManager : MonoBehaviour {

public int currentLevel; // Level 1 starts at 0

public Levels[] levels;

public void SpawnEnemy(){

// Get available Enemy Type at current level. Store all available enemy type in a List.
List<int> availEnemyType = new List<int> ();
for (int i = 0; i < levels[currentLevel].noOfEnemyType.Length; i++) {
if (levels [currentLevel].noOfEnemyType *.count > 0) {*
``````
• `````` 		availEnemyType.Add (i);*
``````
• `````` 	}*
``````
• `````` }*
``````
• `````` if (availEnemyType.Count > 0) { // Check if not null*
``````
• `````` 	int randEnemyIndex = Random.Range (0, availEnemyType.Count); // Randomly pick from available enemy type*
``````
• `````` 	Instantiate (levels [currentLevel].noOfEnemyType [availEnemyType [randEnemyIndex]].enemyType, this.transform); // You know this already :)*
``````
• `````` 	levels [currentLevel].noOfEnemyType [availEnemyType [randEnemyIndex]].count -= 1; // Reduce spawn count of enemy instantiated.*
``````
• `````` } else {*
``````
• `````` 	// What do you want to do after there are no more enemies available? I wonder... Stop spawning I guess.*
``````
• `````` 	Debug.Log ("No More Enemies");*
``````
• `````` }*
``````
• }*
}
You can also use a dictionary or multidimensional array but the problem with those is that they don’t appear in the inspector as “[Unity doesn’t know how to serialize a Dictionary][1]” or multidimensional array.
Reference: [Initializing 2D array via inspector - Questions & Answers - Unity Discussions][2]
[1]: Unity - Scripting API: ISerializationCallbackReceiver
[2]: Initializing 2D array via inspector - Questions & Answers - Unity Discussions