Enemy kill counter and time limit.
I'm making a game where you kill waves of enemies and depending on which you kill the most harder ones spawn in their place, however, there are a few things I'm not sure how to do...
So there are 3 enemy types by default (TypeA, TypeB, TypeC) -If you kill 3 TypeA, 2 TypeB and 1 TypeC, TypeA is replaced by Type D (A splice of Type 1 and 3)
After each wave, the calculation is done to see which is killed most and least and changes the spawn entities/rates
This is what I have so far:
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 Transform fireEnemy;
public int enemyCount;
public float spawnRate;
}
public int whichEnemy = 0;
public Wave[] waves;
private int nextWave = 0;
public Transform[] spawnPoints;
public float timeBetweenWaves = 5f;
private float waveCountdown;
private float searchCountdown = 1f;
private SpawnState state = SpawnState.COUNTING;
void Start()
{
if(spawnPoints.Length == 0)
{
Debug.LogError("No Spawn Points Referenced");
}
waveCountdown = timeBetweenWaves;
}
void Update()
{
whichEnemy = Random.Range(1,3);
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() //Add Difficulty Multiplier For More Waves Here
{
Debug.Log("Wave Completed!");
state = SpawnState.COUNTING;
waveCountdown = timeBetweenWaves;
if(nextWave + 1 > waves.Length - 1)
{
nextWave = 0;
Debug.Log("ALL WAVES COMPLETE! Looping...");
}
else
{
nextWave++;
}
}
bool EnemyIsAlive()
{
searchCountdown -= Time.deltaTime;
if(searchCountdown <= 0f)
{
searchCountdown = 1f;
if(GameObject.FindGameObjectWithTag ("Enemy") == null)
{
return false;
}
}
return true;
}
IEnumerator SpawnWave(Wave _wave)
{
Debug.Log("Spawning Wave: " + _wave.name);
state = SpawnState.SPAWNING;
for (int i = 0; i < _wave.enemyCount; i++)
{
SpawnEnemy(_wave.enemy);
yield return new WaitForSeconds(1f / _wave.spawnRate);
}
state = SpawnState.WAITING;
yield break;
}
void SpawnEnemy (Transform _enemy)
{
Debug.Log("Spawning Enemy" + _enemy.name);
if (whichEnemy==1)
{
Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)];
Instantiate(_enemy, _sp.position, _sp.rotation);
}
else
{
Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)];
Instantiate(_enemy, _sp.position, _sp.rotation);
}
}
//Anything beyond here was a WIP
void EnemiesKilled()
{
if(enemyType1.iskilled)
{
enemyType1Counter++;
}
if(enemyType2.iskilled)
{
enemyType2Counter++;
}
if(enemyType3.iskilled)
{
enemyType3Counter++;
}
}
void SpliceEnemies()
{
int enemyType1Counter = 0;
int enemyType2Counter = 0;
int enemyType3Counter = 0;
if (enemyType1Counter > enemyType2Counter)
{
Destroy gameobject.enemyType1;
}
}
}
Any help or information would be much appreciated
Answer by ashishcw · Jan 09, 2020 at 03:46 PM
@DrewWasTaken Answered this on reddit, and posting the same one here too, incase if you missed that one.
Alright, I saw your code on Unity Questions page, and here are few suggestions from my end, but before that, few questions of my own too.
No offence, but the code looks a little messy, I mean a-lot of the things could be improvised, such as inside an update function, you are calling "whichEnemy" variable and assigning it a random value every-time. You are returning a boolean value with EnemyisAlive function, which in-side, runs to find the "gameobjectwithtag" method, and later this function is called in an update. A thing to keep in mind, update function get's called every-single frame, it may hamper the performance.
Since you aimed to use different types of enemies, I don't see any class which has a base level implementation, meaning, if I were you, I could make a base class which will contain all the basic stats such as Type of Enemy, Health, isAlive_Status and much more. and later I could simply inherit the base class to access the base values, since I assume both, enemy as well as your player side may have. "mentioned" common attributes.
Also, line number 130 to 140, what's the difference in both of these calls? Aren't they identical to each other?```if (whichEnemy==1) { Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)]; Instantiate(_enemy, _sp.position, _sp.rotation); } else { Transform _sp = spawnPoints[ Random.Range(0, spawnPoints.Length)]; Instantiate(_enemy, _sp.position, _sp.rotation); } ```
Instantiating and destroying game objects, can eat the memory, try object pooling. Some interesting facts about object pooling vs creating/destroying objects. https://forum.unity.com/threads/my-experiments-with-object-pooling-versus-instantiate-destroy.258507/
Anyway, back to your question, In-order to create different enemies, and replacing the next one more harder, you could try defining enum(just like you did with spawnstate) and later, with a simple switch case statement, you could assign/increase the value of it's health and damage given to player.
P.S. Try using small and more relavent variable names, e.g. you can call, "whichEnemy" as "enemy_type"
Lastly, please don't get offended, as these are the suggestions. :)
Thank you for your reply, I'll admit the code is a mess. No offense taken I'm a complete novice and am grateful for any feedback/input.
$$anonymous$$ost of the things you mentioned I half implemented then never used them in the end so they are soon to be deleted.
I have a separate Enemy class which contains all the stats.
Could you give me and example of how the Enum Enemy would look laid out? Like I said I'm a complete novice and I keep looping in circles
Thanks again :)
@DrewWasTaken Sorry for the delayed response. well make an enum just like your created earlier. ``` enum Enemy_Type { Normal_Enemy = 0, $$anonymous$$edium_Enemy = 1, Hard_Enemy = 2};
//$$anonymous$$ake an object reference to the enum private Enemy_Type enemy_type; ```
Now inside your awake/start method, simply call, ``` enemy_type = Enemy_Type.Normal //Or anything you wish to assign to ```
Now, inside the Game_$$anonymous$$anager's script(Or the script which is responsible for your base game driven factors(Such as game gradually increasing difficulty etc), a simple "switch" statement would do the job.
Also, if you want, you can put Random.Range function to use too, since, enum types can return an array.
Your answer
Follow this Question
Related Questions
Infinite wave spawner help 0 Answers
How to make a Hollow Knight/Mario style jump in C#? 0 Answers
Cannot detect trigger 2 Answers