简体   繁体   中英

Unity - WaitForSeconds Not Working Inside Update or a Loop

I am trying to instantiate an object continuously. To do this, I need to have some sort of interval or wait timer so it doesn't instantiate everything at once. I came up with this:

public class EnemySpawner : MonoBehaviour
{
     public GameObject Enemy;

     public void Update()
     {
          var random = new Random();
          var randomX = random.Next(-12, 12);
          var randomY = random.Next(-5, 5); 
          StartCoroutine(Spawn(randomX, randomY));
     }

     public IEnumerator Spawn(int randomX, int randomY)
     {
          yield return new WaitForSeconds(3);
          Instantiate(Enemy, new Vector3(randomX, randomY), Quaternion.identity);
     }
}

What ends up happening is that it will wait for 3 seconds (as coded) and then instantiate as many objects as it can at once. The result I was hoping for was that it would spawn one, wait three seconds, spawn another one etc... Any information would be greatly appreciated!

As Josh already commented, you start a new coroutine everytime your update method runs.

To fix this, you can:

either start your coroutine somewhere else (in the start() method if it should run from the beginning)

public void Start() {
    StartCoroutine(Spawn(randomX, randomY));
}

or if the coroutine needs to be called by your update for whatever reason, you can use something like this:

private bool spawnCoroutineStarted = false;

public void Update() {
    // other code
    if (!spawnCoroutineStarted) {
        spawnCoroutineStarted = true;
        StartCoroutine(Spawn(randomX, randomY));
    }
}

EDIT: Thanks to Draco18s, for pointing out my oversight.

To spawn enemies continuously you could change the Spawn method like this:

public IEnumerator Spawn(randomX, randomY) {
    while (true) {
        yield return new WaitForSeconds(3);
        Instantiate(Enemy, new Vector3(randomX, randomY), Quaternion.identity);
    }
}

Keep in mind, that if you want to use StopCoroutine later on you have to store the IEnumerator returned by Spawn and use the StopCoroutine method on that reference.

Also, if you really want to have something reoccuring over a specific time frame you might want to consider using InvokeRepeating instead of coroutines.

If you want it to continually spawn, you could use a touch of recursion.

void Start()
{        
    StartCoroutine(Spawn());
}

public IEnumerator Spawn()
 {
    yield return new WaitForSeconds(3);
    var random = new Random();
    var randomX = random.Next(-12, 12);
    var randomY = random.Next(-5, 5); 
    Instantiate(Enemy, new Vector3(randomX, randomY), Quaternion.identity);
    StartCoroutine(Spawn());
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM