Jack Manning
Jack Manning

Reputation: 1

Coroutine and waitforseconds not working as planned

Hello I've been having trouble with the Coroutine function and wait for seconds. After clicking a button my code should:

However what i get is:

How can I get it so that the wait stops the code carrying on for the time correctly.

IEnumerator wait(){ // This is the function to call it to wait
    Debug.Log ("Before Wait");
    yield return new WaitForSeconds (2);
    Debug.Log ("After Wait");
}

void Update () {

    if (chosen == false) {
        if (choice != "")
            chosen = true;
    }

    if (chosen == true){
        enemyChoice = "";
        int n = rnd.Next(num.Count);
        enemyChoice = choices [n];
        Debug.Log (choice); // Here choice should be printed, then the coroutine started and then enemy choice printed
        StartCoroutine (wait ());
        Debug.Log (enemyChoice);
        chosen = false;
        toDecide = true;
        }


    if (toDecide == true){ // sorry for the clunky way of deciding the result
        if (choice == enemyChoice) {
            Debug.Log ("Draw");
        } else if (choice == "rock" && enemyChoice == "paper") {
            Debug.Log ("Lose");
        } else if (choice == "rock" && enemyChoice == "scissors") {
            Debug.Log ("Win");
        } else if (choice == "paper" && enemyChoice == "rock") {
            Debug.Log ("Win");
        } else if (choice == "paper" && enemyChoice == "scissors") {
            Debug.Log ("Lose");
        } else if (choice == "scissors" && enemyChoice == "paper") {
            Debug.Log ("Win");
        } else if (choice == "scissors" && enemyChoice == "rock") {
            Debug.Log ("Lose");
        } else {
            Debug.Log ("Error");
        }

        toDecide = false;
        choice = "";
        enemyChoice = "";
    }
}  

Upvotes: 0

Views: 2538

Answers (2)

mayo
mayo

Reputation: 4105

First you have to understand that Update is a method that is called every frame. Again and again.

If your game is hitting 60 frames per second, this means that Update will be called 60 times per second (You can check this adding Debug.Log("Update!"); in Update()).

Now, if you want to have some logic that waits for x seconds it should be outside Update, because, as we know Update will be called again and again, without caring about any WaitForSeconds.

Here is a simple example of two methods (well, one is a method and another is a coroutine) and the result of the execution:

// Use this for initialization
void Start() 
{
    Method1();
    StartCoroutine(Method2CR());
}

// Update is called once per frame
void Update() {
    // I don't want call my methods/Coroutines many times per frame..
}

IEnumerator Wait5Seconds()
{
    yield return new WaitForSeconds(5f);
}

void Method1()
{
    Debug.Log("Method1 before Wait5Seconds: " + Time.time);
    StartCoroutine(Wait5Seconds());
    Debug.Log("Method1 after Wait5Seconds: "+ Time.time);
}

IEnumerator Method2CR()
{
    Debug.Log("Method2CR before Wait5Seconds: "+ Time.time);
    yield return StartCoroutine(Wait5Seconds());
    Debug.Log("Method2CR after Wait5Seconds: " + Time.time);
}

and the output is:

Method1 before Wait5Seconds: 0
Method1 after Wait5Seconds: 0
Method2CR before Wait5Seconds: 0
Method2CR after Wait5Seconds: 5.010797

You can read this to get an idea of what is going on behind the scenes on Monobehaviour elements. Look at the Script Lifecycle Flowchart picture.

Upvotes: 2

Hellium
Hellium

Reputation: 7356

Similar questions have been asked many times before, on StackOverflow and on Unity Answers.

Coroutines do not pause the execution of the function they have been called into. You have to put your logic inside a big coroutine instead :

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

IEnumerator GameLogic () {

    while (true )
    {
        if (chosen == false) {
            if (choice != "")
                chosen = true;
        }

        if (chosen == true){
            enemyChoice = "";
            int n = rnd.Next(num.Count);
            enemyChoice = choices [n];
            Debug.Log (choice); // Here choice should be printed, then the coroutine started and then enemy choice printed

            Debug.Log ("Before Wait");
            yield return new WaitForSeconds (2);
            Debug.Log ("After Wait");

            Debug.Log (enemyChoice);
            chosen = false;
            toDecide = true;
        }


        if (toDecide == true){ // sorry for the clunky way of deciding the result
            if (choice == enemyChoice) {
                Debug.Log ("Draw");
            } else if (choice == "rock" && enemyChoice == "paper") {
                Debug.Log ("Lose");
            } else if (choice == "rock" && enemyChoice == "scissors") {
                Debug.Log ("Win");
            } else if (choice == "paper" && enemyChoice == "rock") {
                Debug.Log ("Win");
            } else if (choice == "paper" && enemyChoice == "scissors") {
                Debug.Log ("Lose");
            } else if (choice == "scissors" && enemyChoice == "paper") {
                Debug.Log ("Win");
            } else if (choice == "scissors" && enemyChoice == "rock") {
                Debug.Log ("Lose");
            } else {
                Debug.Log ("Error");
            }

            toDecide = false;
            choice = "";
            enemyChoice = "";
        }

        yield return null ; // To wait one frame
    }
}

Upvotes: 1

Related Questions