Working with Weighted Tables in Unity3D
Objective: Create a balanced spawn system for the power-ups using a weighted table where more common power-ups, like ammo and health, spawn more frequently, and rare power-ups, like the Laser Beam, spawn more infrequently.
Step 1: In the SpawnManager script, create a private int array called _table and set a value for each power-up from largest to smallest. The larger the value, the more often that power-up will spawn.
Step 2: Create two private int variables called _total and _randomNumber.
Step 3: Create a private GameObject List called _powerUps.
Step 4: In Unity, select the Spawn_Manager GameObject in the Hierarchy window and add 7 elements to the Power Ups List in the Inspector window. Then drag and drop each power-up Prefab into the slots according to its weight value in the _table array.
Step 5: In the SpawnManager script, within the Start() method, create a foreach loop stating for each item in the _table array, have the value of the _total variable equal to the _total plus the value of the item variable, which is the sum of the power-up weight values, and in this case, _total = 100.
Step 6: In the SpawnPowerUpRoutine() coroutine, within the while loop, while _stopSpawning is false, set a yield return of 5–10 seconds. Then set the value of the _randomNumber variable to a random range between 0 and _total, which is 100.
Step 7: Create an else statement under the if statement with the break that is triggered if _stopSpawning equals true. Within the else statement, create a for loop where int i equals 0, and while i is less than the length of the _table array, check if the _randomNumber value is less than or equal to the current value of i, which is Element 0 in the _table array. If the value is less than or equal, the power-up associated with Element 0 in the _powerUp List will spawn between a random range on the X-axis, then the loop will break.
But if the _randomNumber value is greater than i in the current table, then the value of _randomNumber will equal the current value of _randomNumber minus the value of i, or Element 0, in the _table array, which in this case is 30. Then, the value of i will increment and the for loop will repeat, but now checking if the new value of _randomNumber is less than or equal to i, which now is Element 1 in the _table array.
Step 8: Now, the SpawnPowerUpRoutine() needs to be restarted. At the top of the script, create a private bool variable called _powerUpSpawn and set it to false.
Step 9: Create a new private method called RestartPowerUpSpawnRoutine(). Create an if statement stating that if _powerUpSpawn is true, immediately set it back to false and start the SpawnPowerUpRoutine() coroutine.
Step 10: Within the SpawnPowerUpRoutine() coroutine, inside the if statement in the for loop, after the power-up instantiation and before the break, add _powerUpSpawn is true. This will trigger the coroutine to restart after it breaks out of the loop.
Step 11: In the Update() method, call the RestartPowerUpSpawnRoutine() method, which will check every frame to see if _powerUpSpawn is true.
Now the power-ups will spawn every 5–10 seconds with better spawn balancing between common power-ups and rarer power-ups.