The question is answered, right answer was accepted.
I want to make a Monster Spawner that spawns a monster in every x seconds (in real time); but I can't get timer to work properly...
I'm trying to make a Spawner, which will Instantiate a prefab in every x seconds. I tried many times, but I can't get coroutines to work properly. This is the last form of code; which waits x seconds before spawning any prefab; after that, summons all monsters immediately. I don't know what am I missing; any help will be welcomed!
TY for taking time!
using System.Collections;
using UnityEngine;
public class MonsterSpawner : MonoBehaviour
{
public GameObject[] spawnPoints;
public int monstersCount;
public GameObject monster2;
private GameObject monsterSprite;
public float spawnDelay = 5f;
void FixedUpdate()
{
if (monstersCount < 1)
Destroy(gameObject);
StartCoroutine(SpawnMonster());
}
IEnumerator SpawnMonster()
{
yield return new WaitForSecondsRealtime(spawnDelay);
int pointSelected = Random.Range(0, 3); //To use as index for reaching array of spawn points.
Vector2 pointToSpawn = spawnPoints[pointSelected].transform.position;
GameObject clonePrefab = Instantiate(monster2, pointToSpawn, Quaternion.identity);
monsterSprite = clonePrefab.transform.GetChild(0).gameObject;
if (pointSelected == 1)
monsterSprite.GetComponent<SpriteRenderer>().flipX = true;
else
monsterSprite.GetComponent<SpriteRenderer>().flipX = false;
monstersCount--;
}
}
Answer by WarmedxMints · Mar 28, 2019 at 09:29 PM
The problem is you are starting a new co-routine every physics tick. I'm not sure why you are using fixed update. You could use a while statement in the coroutine and just start it once. Like so;
using System.Collections;
using UnityEngine;
public class MonsterSpawner : MonoBehaviour
{
//You may as well use transform here rather than gameobjects
public Transform[] SpawnPoints;
public int MonstersCount;
public GameObject Monster2;
[SerializeField]
private float _spawnDelay = 5f;
private WaitForSecondsRealtime _waitTime;
private void Start()
{
_waitTime = new WaitForSecondsRealtime(_spawnDelay);
StartCoroutine(SpawnMonster());
}
IEnumerator SpawnMonster()
{
while (MonstersCount >= 1)
{
var pointSelected = Random.Range(0, 3); //To use as index for reaching array of spawn points.
var pointToSpawn = SpawnPoints[pointSelected].position;
var clonePrefab = Instantiate(Monster2, pointToSpawn, Quaternion.identity);
var monsterSprite = clonePrefab.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>();
if (monsterSprite != null)
{
monsterSprite.flipX = pointSelected == 1;
}
MonstersCount--;
yield return _waitTime;
}
Destroy(gameObject);
}
}
You could also use a timer in the update method and do away with the coroutine if you wish or create a method you could call to spawn x monsters whenever you wish rather than destroying the spawner.
Thank you for the answer! I don't have much practice in C#, it takes a while to get best solution. I was using FixedUpdate to prevent frames from having different life-times, so there will be no frame-delays because of a frame that needs more time to complete calculations it needs to do.
I was destroying the Spawner, because even if monstersCount is <1, Update will keep checking if state. I wanted to prevent unnecessary calculations...
And also thanks for maintaining my code, I will consider your code while re-writing my script.
Cheers ^^