Paul Balan Paul Balan - 3 months ago 18
C# Question

Why isn't my "yield" working?

i'm very new to programming and i have a feeling that there is a very stupid mistake here. But can anyone explain me, why instead of 4 messages with a delay of 2 seconds between, i instantaniously get the last message shown only.

using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using UnityEngine.UI;

public class Wait : MonoBehaviour {

private int i = 0;
public string[] message;

[SerializeField]
private Text toText;

public IEnumerator Message(float waitTime)
{
toText.text = message[i];
i++;
yield return new WaitForSeconds(waitTime = 2f);
}

void Start()
{
StartCoroutine(Message(i));
StartCoroutine(Message(i));
StartCoroutine(Message(i));
StartCoroutine(Message(i));
}
}

Answer
void Start()
{
    StartCoroutine(Message(i));
    StartCoroutine(Message(i));
    StartCoroutine(Message(i));
    StartCoroutine(Message(i));
}

I don't think that is doing what you think it should. This will not wait for each StartCoroutine to finish and will call the next StartCoroutine.

This is what happens:

The first StartCoroutine(Message(i)); call will start the Message function. Once it meets the yield return new WaitForSeconds(waitTime = 2f); line of code, it will then jump back into the Start() function.

The next StartCoroutine(Message(i)); will be called then the-same thing will happen again.

When calling a coroutine function from a non coroutine function, as long as you have yield return new WaitForSeconds, yield return null;, or yield return what-ever YieldInstruction is implemented, the execution will return to that non coroutine function in-which the StartCoroutine function was called from and continue to execute other code.

To make coroutine wait for another one to finish, make the StartCoroutine(Message(i)); function call from another coroutine function. This will allow you to yield each coroutine function call. This is called chaining coroutine.

To chain or yield a coroutine function call, simply put yield return in front of the StartCoroutine function. yield return StartCoroutine(Message(i));

public class Wait : MonoBehaviour {
    private int i = 0;
    public string[] message;

    [SerializeField]
    private Text toText;

    public IEnumerator Message(float waitTime)
    {
        // toText.text = message[i];
        i++;
        yield return new WaitForSeconds(waitTime = 2f);
    }

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

    IEnumerator startMessage()
    {
        yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns
        yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns
        yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns
        yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns
    }
}

Now, each StartCoroutine(Message(i)); call will wait until the first one finishes. You can always use a boolean variable to do this but it is much better to yield the StartCoroutine call.