Created
October 11, 2015 21:00
-
-
Save fiskefyren/165230f20f6d19c1619d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public class WaveSpawner : MonoBehaviour { | |
public enum SpawnState { SPAWNING, WAITING, COUNTING }; | |
[System.Serializable] | |
public class Wave { | |
public string name;//name of the wave | |
public Transform enemy;//reference to prefab | |
public int count;//the amount of enemies for a wave | |
public float rate;//the spawn rate, the higher the number the faster they spawn | |
} | |
public Wave[] waves; | |
private int nextWave = 0;//stores the index of the next coming wave | |
public Transform[] spawnPoints;//the enemies spawn from these points | |
public float timeBetweenWaves = 5f;//stores the time between waves in seconds | |
private float waveCountdown;//? | |
private float searchCountdown = 1f;//this is used for our EnemyIsAlive checker method, so that it updates for every second rather than every frame | |
private SpawnState state = SpawnState.COUNTING; | |
void Start() { | |
if (spawnPoints.Length == 0) { | |
Debug.LogError("No spawn points referenced."); | |
} | |
waveCountdown = timeBetweenWaves;//which is currently 5 seconds | |
} | |
void Update () { | |
//killing off the entire wave before a new one spawns | |
if (state==SpawnState.WAITING) { | |
//check if enemies are still alive | |
if (!EnemyIsAlive()) {//this will check if we've any enemies in the screen, FYI !EnemyIsAlive() is the same as EnemyIsAlive()==false | |
//begin a new round | |
WaveCompleted(); | |
return; | |
} | |
else {//if we still have enemies alive then we want to return | |
return; | |
} | |
} | |
if(waveCountdown <= 0) { | |
if (state != SpawnState.SPAWNING) { | |
//start spawning wave | |
StartCoroutine(SpawnWave(waves[nextWave])); | |
} | |
} | |
else { | |
waveCountdown -= Time.deltaTime;//makes sure that the countdown timer stays relevant to time rather than to frames drawn/second, which is currently going to count down from 5 | |
} | |
} | |
void WaveCompleted() { //being new round | |
Debug.Log("Wave completed"); | |
state = SpawnState.COUNTING;//counting down | |
waveCountdown = timeBetweenWaves; | |
if (nextWave + 1 > waves.Length - 1) { //current wave + 1 = next wave, waves.Lenght is the number of waves | |
nextWave = 0;//it'll go back and spawn the first wave again | |
//here would be the ideal place to put a finish screen e.g. "Yay! You've finished the game!" or increase the stats of the enemies | |
Debug.Log("Completed all waves! Looping..."); | |
} | |
else { | |
nextWave++;//if you haven't reached the final wave and completed it yet, then this will just continue you to the next level | |
} | |
} | |
//this is very resource demanding, so rather than updating for every frame it should only be updated every second | |
bool EnemyIsAlive () { | |
searchCountdown -= Time.deltaTime; | |
if (searchCountdown <= 0f) {//if searchCountdown is less or equal to 0 seconds then it will run the next if statement below | |
searchCountdown = 1f;//when our countdown reaches 0 and enemies are still alive then we want the countdown to check again in one second | |
if (GameObject.FindGameObjectsWithTag("Enemy") == null) {//returns an array of all enemies/gameobjects with this game tag | |
return false;//meaning that no enemies are alive, so if that's the case then the next wave WILL spawn | |
} | |
} | |
return true;//meaning that some enemies are alive, so if that's the case then the next wave WON'T spawn | |
} | |
IEnumerator SpawnWave(Wave _wave) {//waits a certain amount of seconds inside of the method, which is why we're using IEnumerator rather than a void | |
Debug.Log("Spawning Wave: "+ _wave.name); | |
state = SpawnState.SPAWNING; | |
//spawn | |
for (int i = 0; i < _wave.count; i++) {//will run the amount of enemies we want to spawn | |
//spawn an enemy | |
SpawnEnemy(_wave.enemy); | |
yield return new WaitForSeconds(1f / _wave.rate);//waits a certain amount of seconds before looping again and spawning a new enemy, this is why we're using IEnumerator | |
} | |
state = SpawnState.WAITING;//? | |
yield break;//will return nothing, always use this when dealing with IEnumerator | |
} | |
//remember to go to prefabs and tag the enemy as "Enemy" in the inspector for all the enemies you want to be spawning | |
void SpawnEnemy (Transform _enemy) { | |
Debug.Log("Spawning Enemy: " + _enemy.name); | |
Transform _sp = spawnPoints[Random.Range(0,spawnPoints.Length)];//? | |
//enemy spawn point | |
Instantiate(_enemy, _sp.position, _sp.rotation); | |
//Instantiate(_enemy, transform.position, transform.rotation);//spawn point location //you can also use Vector3 if you like | |
} | |
} | |
/* | |
after finishing the code: | |
create an empty gameobject in Unity -> name it EnemySpawnPoint -> give it an icon so it's easier to see -> make it into a prefab -> | |
then you can make multiple spawn points if you desire (the Random.Range at line 110 should make enemies spawn from one of the spawn points randomly) -> | |
drag all of the spawn points into the spawn points elements where the C# Script has been added to -> hit apply and you should be done! | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment