- Home /
I'm having trouble with a coroutine delay
shouldnt this work? I put a delay before the Spawnloop delay. contents are in the NewDelay function.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObstacleSpawner : MonoBehaviour
{
public int obstacles_min = 1;
public int obstacles_max = 4;
public float obstacles_range= 10;
public float obstacles_deviation_min = -3;
public float obstacles_deviation_max = 3;
public Transform playerTransform;
public GameObject obstaclePrefab;
public float obstacleLifetime = 4f;
public float spawnDelay = 3;
public float BeginingDelay = 4;
// Use this for initialization
void Start ()
{
StartCoroutine ("NewDelay");
StartCoroutine ("SpawnLoop");
}
// Update is called once per frame
void Update ()
{
}
private void SpawnObstacles()
{
int randomNumber = Random.Range (obstacles_min, obstacles_max); // Picks a number within min and max and store in randomNumber
for (int i = 0; i < randomNumber; i++)// i = 0 if i is less than the random number stored increment i++ until its reached the value of the random number
{
Vector3 randomPos = new Vector3 (playerTransform.position.x + Random.Range (obstacles_deviation_min, obstacles_deviation_max), playerTransform.position.y, playerTransform.position.z + obstacles_range);
GameObject obstacle = Instantiate (obstaclePrefab, randomPos, Quaternion.identity) as GameObject;
Destroy (obstacle, obstacleLifetime);
}
}
private IEnumerator SpawnLoop()
{
while (true)
{
SpawnObstacles ();
yield return new WaitForSeconds (spawnDelay);
//print ("spawn delayed");
}
yield return null;
}
private IEnumerator NewDelay()
{
yield return new WaitForSeconds (BeginingDelay);
}
}
Answer by merkaba48 · Jul 04, 2017 at 06:46 PM
Your NewDelay coroutine isn't actually doing anything. It runs, waits a bit, then runs again; but what's it doing?
I'm going to make an assumption that you're expecting the Start() method to wait until NewDelay returns before running SpawnLoop - that's now how it works. NewDelay will run, then as soon as it returns, SpawnLoop will run - they do not affect each other. You wouldn't want Start() to wait for NewDelay to finish its WaitForSeconds anyway, as that would lock the entire game up until it's complete (other scripts will only be run when Start(), or any method, has finished executing).
One solution is to use the Invoke method and a new function that simply starts the SpawnLoop , e.g. new function StartSpawning,
void StartSpawning() {
StartCoroutine("SpawnLoop");
}
Then, in your Start, replace everything there with,
Invoke("StartSpawning", BeginingDelay);
Another, perhaps better solution is to keep things how they are, but remove everything to do with NewDelay, then modify SpawnLoop thusly:
private IEnumerator SpawnLoop()
{
yield return new WaitForSeconds(BeginingDelay); // New line
while (true)
{
SpawnObstacles ();
yield return new WaitForSeconds (spawnDelay);
//print ("spawn delayed");
}
yield return null;
}
This means the first time the Coroutine is run, it waits for BeginingDelay (btw it's spelt "Beginning" :)) seconds, and then carries on to the rest of the Coroutine.
Thanks! I don't know why I didnt just think of putting a delay in the spawnloop function. Great Thinking!
Answer by Cornelis-de-Jager · Jul 05, 2017 at 01:14 AM
Hi SeanWink,
The problem is in your start function.
void Start ()
{
StartCoroutine ("NewDelay");
StartCoroutine ("SpawnLoop");
}
The issue is that the StartCoroutine function doesn't Add a delay. It creates a new function that runs at the same time as your start function. So everything in your Start function gets executed instantly. To solve this do the following:
void Start ()
{
StartCoroutine ("NewDelay");
// Remove the coroutine from here
}
private IEnumerator NewDelay()
{
yield return new WaitForSeconds (BeginingDelay);
StartCoroutine ("SpawnLoop"); // Add it here after the delay
}