user3609339
user3609339

Reputation: 13

Waitforseconds is not waiting

I have this code which is loaded when you finish a game level. It should freeze the time, scale the level completed message, wait 5 seconds and then load next level and unfreeze time. The problem is that the WaitForSeconds is not working. It just loads the next level without waiting. What am I doing wrong?

IEnumerator WaitingFunction(){
    yield return new WaitForSeconds(5);
}

void OnTriggerEnter ( Collider col )
{
    if (col.tag == "Player")
    {
        Time.timeScale = 0f;
        lvlcomplete.transform.localScale = new Vector3 (1,1,1);

        StartCoroutine(WaitingFunction());

        Time.timeScale = 1f;
        lvlcomplete.transform.localScale = new Vector3 (0,0,0);
        Application.LoadLevel(Application.loadedLevel+1);
        player.transform.position = new Vector3(0f, 0.3519309f, -2.381933f);
    }

Upvotes: 1

Views: 1802

Answers (3)

Kay
Kay

Reputation: 13146

Like LearnCocos2D said you have to move the code. Further on to get this working with timeScale = 0 you simply need to let this wait for the corresponding number of frames:

IEnumerator WaitingFunction(){
    int noOfFramesToWait = (int)(seconds * Application.targetFrameRate);
    for (int i = 0; i < noOfFramesToWait; i++) {
        yield return null;
    }
    Time.timeScale = 1f;
    // do my stuff
}

If you have a couple of situations like pausing, additive level loading, game over, fading in and out,.. the next step can be get this more generic:

void OnTriggerEnter ( Collider col ) {
    if (col.tag == "Player") {
        Time.timeScale = 0f;
        StartCoroutine (WaitForNFrames (5f, LoadNewLevel));
    }
}

public void LoadNewLevel () {
    Time.timeScale = 1f;
    // do my stuff
}

IEnumerator WaitForNFrames (float seconds, System.Action executeWhenFinished) {
    int noOfFramesToWait = (int)(seconds * Application.targetFrameRate);
    for (int i = 0; i < noOfFramesToWait; i++) {
        yield return null;
    }
    executeWhenFinished ();
}

Another small thing, maybe you have this already: You reference the player object after calling LoadLevel. Ensure that it is not destroyed when the new level is loaded by using DontDestroyOnLoad.

Upvotes: 1

Vectoria
Vectoria

Reputation: 1687

Try restructuring your code as follows

WaitingFunction(){
    yield WaitForSeconds (5);
}

void OnTriggerEnter ( Collider col )
{
    if (col.tag == "Player")
    {
        Time.timeScale = 0f;
        lvlcomplete.transform.localScale = new Vector3 (1,1,1);

        StartCoroutine(WaitingFunction());

        Time.timeScale = 1f;
        lvlcomplete.transform.localScale = new Vector3 (0,0,0);
        Application.LoadLevel(Application.loadedLevel+1);
        player.transform.position = new Vector3(0f, 0.3519309f, -2.381933f);

                }

Upvotes: -2

CodeSmile
CodeSmile

Reputation: 64477

You start a coroutine that waits 5 seconds without doing anything while the OnTriggerEnter code continues to load the level instantly.

You should move the code that should run after the wait time has passed inside the coroutine:

IEnumerator WaitingFunction(){
    yield return new WaitForSeconds(5);

    Time.timeScale = 1f;
    lvlcomplete.transform.localScale = new Vector3 (0,0,0);
    Application.LoadLevel(Application.loadedLevel+1);
    player.transform.position = new Vector3(0f, 0.3519309f, -2.381933f);
}

Upvotes: 2

Related Questions