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.