WaitforSeconds not exactly waiting for the time specified in Unity

3.3k views Asked by At

I searched for using WaitforSeconds and used as it was mentioned(using a return type of IEnumeration and using coroutines instead of update). but it did not work. Initially it showed Waitfor Seconds and IEnumerator were not "present in the current context". I had to r-install unity to get it fixed but this problem still remains. The following is my code. Am I using WaitforSeconds in correct way? Is it the 'if' code block that ruin my complete work(I mean have I used it in wrong place)?

using UnityEngine;
using System.Collections;

public class EnemyCreeator : MonoBehaviour 
{
    public float xmin,xmax,zmin,zmax;
    public GameObject enemy;
    public float spawnWait,StartWait,waveWait;
    public int turretCount;
    public int enemyCount;
    int i=0;

    void Update() 
    {
        StartCoroutine (TurretWaves());
    }

    IEnumerator TurretWaves()
    {
        while (true) 
        {  
            Vector3 pos=new Vector3(Random.Range (xmin,xmax),0.5f,Random.Range(zmin,zmax));
            yield return new WaitForSeconds(StartWait);
            while(i<turretCount) 
            {
                //Debug.Log ("The vaue of game time in spawnwaiting is: "+Time.time);
                Instantiate (enemy, pos, Quaternion.identity);
                enemyCount++;
                i++;
                //Debug.Log ("value of i in loop is: "+i);
                //Debug.Log ("The vaue of game time is: "+Time.time);
                yield return new WaitForSeconds (spawnWait);
            }

            //Debug.Log("cHECKing Before WAVE WAIT(value of time )is: "+Time.time);
            yield return new WaitForSeconds(waveWait);
            if(i>=turretCount)
            {
                i=0;
            }
            //Debug.Log("cHECKing AFTER WAVE WAIT and value of time is: "+Time.time);
            //Debug.Log ("value of i outside the while loop is: "+i);
        }
    }
}

The code needs to wait until the spawnWait before spawning each turret and wait till the wavewait before spawning the next wave. even though the Startwait works fine, I still am unable to find the problem with others...

Thanks in advance.

1

There are 1 answers

3
Andy Lee On

Your code is correct, except

void Update()
{
    StartCoroutine (TurretWaves());
}

By doing this, you are creating a new coroutine in every frame. Therefore, after Startwait seconds, each running coroutine will spawn an enemy in the following frames, making the overall script works incorrectly. But, in fact, each coroutine works as you expected.

To solve your problem, change

void Update()

to

void Awake()

or

void Start()

such that only one coroutine is started. It should work as expected.

Edit #1:

I think you misunderstood how coroutine works in Unity, because it seems that you are using Update to manually execute the code inside coroutine frame by frame.

When a coroutine is started by StartCoroutine, a "task" will be registered inside Unity. This task is like another thread (except it is still in the main thread). Unity will execute the code inside this task automatically. When it meets a yield statement, it pauses and waits for the statement to end. (Internally, it checks the state continuously and determine when it should resume.) For example, yield return new WaitForSeconds(n) will make Unity temporarily stops executing the code inside the coroutine for n seconds. And after that, it will keep going on.

The task will be deregistered until no more code should be executed (in your case, it never ends because of the while-loop), or the game object that started the coroutine is destroyed or deactivated.