Spawn System Working but not the way i want

Hi there and thanks for looking. I need some help with my spawn system it works great but i want it to be better and easier to edit at runtime. The whole thing works of off a percentage chance to spawn at the minute i have something that goes like this

zzzsssnnnn

12345678910

z = zombie
s = skeleton
n = nothing

so Zombie has 30% chance
Skeleton has 30% chance
and nothing has 40% chance

I want to be able to just assign a % chance to each enemy and then spawn that enemy based on it’s percentage here is the whole code. If you look at Waves() you will see how i currently assign the percentage to spawn i want this to be easier if someone out there could help that would be great.

using UnityEngine;
using System.Collections;

public class SpawnSystem : MonoBehaviour {
    //our variables
    public int minEnemies;
    public int maxEnemies;
    public int maxEnemiesPerWave = 20; // max enemies to spawn not for the wholoe round this is for performance
    public int currentEnemies;
    public int currentWave;
    public float spawnInterval;
    public float random;
    public int wytches = 0;
    public int totalEnemiesForThisRound = 50; // Max enemies to have for the whole round 
    public int enemiesSpawnedThisWave;// here it would be like how many to spawn ie not max enemies but a threshold 
    public Transform[] spawnPoints;
    [System.Serializable]
    public class Enemy
    {
        public string enemyName;
        public int minPercentageToSpawn;
        public int maxPercentageToSpawn;
        public GameObject enemy;
    }

    public Enemy[] enemies = new Enemy[11];

    // Use this for initialization
	void Start ()
    {
        currentWave = 1;
        totalEnemiesForThisRound = 50;
        Waves();
        StartCoroutine(SpawnLoop());
       
    }
    IEnumerator SpawnLoop()
    {
        while(true)
        {
            SpawnEnemies();
            yield return new WaitForSeconds(spawnInterval);
        }
    }

	// Update is called once per frame
	
    void Update () 
    {
        if (enemiesSpawnedThisWave == totalEnemiesForThisRound)
        {
            enemiesSpawnedThisWave = 0;
            totalEnemiesForThisRound += 20;
            currentWave += 1;
            Waves();
        }
	}

    

    void SpawnEnemies() // start creating some enemies
    {
        if (currentEnemies <= maxEnemiesPerWave && enemiesSpawnedThisWave != totalEnemiesForThisRound)
        {

            for (int l_enemy = 0; l_enemy < enemies.Length; l_enemy++)
            {
                random = Random.Range(1, 11);
                if (random <= enemies[l_enemy].maxPercentageToSpawn && random >= enemies[l_enemy].minPercentageToSpawn)
                {
                    Debug.Log(random);
                    Transform l_obj = spawnPoints[Random.Range(0, spawnPoints.Length)];
                    Instantiate(enemies[l_enemy].enemy, l_obj.position, l_obj.rotation);
                    currentEnemies += 1;
                    enemiesSpawnedThisWave += 1;
                }
            }
        }
    }

    void Waves()
    {
        switch (currentWave)
        {
            case 1:// count the min and max to get the % to spawn so 5-9 = 50% 5-6-7-8-9 10% for each number
                enemies[0].maxPercentageToSpawn = 5;
                enemies[0].minPercentageToSpawn = 1;
                enemies[1].maxPercentageToSpawn = 10;
                enemies[1].minPercentageToSpawn = 6;
                break;
            case 2:
                enemies[0].maxPercentageToSpawn = 2;
                enemies[0].minPercentageToSpawn = 0;
                enemies[1].maxPercentageToSpawn = 6;
                enemies[1].minPercentageToSpawn = 3;
                break;
            default:
                break;
        }
    }
}

You could simplify the Enemy class to just hold the percentage, and use Random.Range(0, 100) to draw a number in the range 0…99. If you want to spawn at most one enemy each time SpawnEnemies is called, draw the number before the for and use two auxiliary variables (lowLim and hiLim) to calculate the range for each enemy. Supposing the chances for enemy 0 and 1 are 30% and 25%, for instance, the code below will instantiate enemy 0 if random >= 0 and < 30, and enemy 1 if random >= 30 and < 55:

    ...
    public class Enemy
    {
        public string enemyName;
        public int chanceToSpawn; // define the percentage here (0..100)
        public GameObject enemy;
    }
    ...
    void SpawnEnemies() // start creating some enemies
    {
        if (currentEnemies <= maxEnemiesPerWave && enemiesSpawnedThisWave != totalEnemiesForThisRound)
        {

            random = Random.Range(0, 100); // draw a number between 0 and 99
            int lowLim;    // lowLim and hiLim are automatically set for each enemy
            int hiLim = 0;
            for (int l_enemy = 0; l_enemy < enemies.Length; l_enemy++)
            {
                lowLim = hiLim; // set low limit...
                hiLim += enemies[l_enemy].chanceToSpawn; // and high limit
                if (random >= lowLim && random < hiLim)
                { // instantiate it!
                    Debug.Log(random);
                    Transform l_obj = spawnPoints[Random.Range(0, spawnPoints.Length)];
                    Instantiate(enemies[l_enemy].enemy, l_obj.position, l_obj.rotation);
                    currentEnemies += 1;
                    enemiesSpawnedThisWave += 1;
                }
            }
        }
    }

    void Waves()
    {
        switch (currentWave) // define the percentage for each enemy
        {
            case 1:
                enemies[0].chanceToSpawn = 50;
                enemies[1].chanceToSpawn = 50;
                break;
            case 2:
                enemies[0].chanceToSpawn = 30;
                enemies[1].chanceToSpawn = 30;
                break;
            default:
                break;
        }
    }
}

I’m using a similar system for something in my game. This is modified version of that script where I’ve added an array in place of your random generation. As a best practice it’s usually preferable hand create randomness through tables as truly random generation could lead to the same enemy (or no enemy) 50 times in a row. This way you can put in an enemy that comes in once every 50 times (or however long your table of enemy Prefabs is)

public class EnemyWaveGenerator : MonoBehaviour {

	GameObject[] enemy;						//pool of baddies to be spawned
	int activeEnemy = 0;					//counter
	float frequency = 1.0f;					//time between spawns
	int enemyCache = 50;					//number of enemies in the pool
	int waveSize = 20;						//number of enemies in the wave

	public GameObject[] enemyPrefab;		//enemy prefabs go in here in whatever order you want
	public Transform[] spawnPoints;			//places to spawn enemies

	int curSpawnPoint;						//counter for enemy placement

	float timeLastEnemyActivated;			//timer for when the last enemy was spawned

	int enemiesSpawnedThisWave = 0;
	int totalEnemiesForThisRound = 50;
	int currentWave = 0;

	void Awake () {
	
		enemy = new GameObject[enemyCache];
		int count=0;

		for(int i=0; i<enemy.Length; i++){

			enemy *= Instantiate(enemyPrefab[count]) as GameObject;*

_ enemy*.active = false;_
_
count++;_
_
if(count>enemyPrefab.Length)_
_
count = 0;*_

* }*

* }*

* void Update () {*

* if (totalEnemiesForThisRound < enemiesSpawnedThisWave)*
* if(Time.time > timeLastEnemyActivated + frequency)*
* spawnEnemy();*
* else*
* nextWave();*

* }*
* void nextWave (){*

* enemiesSpawnedThisWave = 0;*
* totalEnemiesForThisRound += 20;*
* currentWave += 1;*

* }*
* void spawnEnemy (){ *

* timeLastEnemyActivated = Time.time - frequency;*
* if(!enemy[activeEnemy].active){*
* enemy[activeEnemy].active = true;*
* enemy[activeEnemy].transform = spawnPoints[curSpawnPoint];*
* curSpawnPoint++;*
* activeEnemy++;*
* enemiesSpawnedThisWave++;*
* }*

* if(curSpawnPoint > spawnPoints.Length)*
* curSpawnPoint = 0; //reset the loop*
* if(activeEnemy > enemyCache)*
* activeEnemy = 0; //reset the loop*
* }*
}