为什么我的 "yield" 不工作?

Why isn't my "yield" working?

我是编程的新手,我觉得这里有一个非常愚蠢的错误。但是谁能解释一下,为什么我立即只显示最后一条消息,而不是 4 条消息之间有 2 秒的延迟。

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));
    }
}

立即设置文本的原因是因为 StartCoroutine 将从 Message.

执行枚举器

发生的前两件事是设置文本和递增 i。只有在完成之后,您才会产生 WaitForSeconds。正是在这一点 StartCoroutine 将暂停 Message.

的进一步执行

如果您在 yield return 之后有一行,您会在 2 秒后看到它的效果。

在文档的示例中,您还可以看到 yield return Wait 之后的行为 https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html

我建议 运行 进行下一次测试,以更加熟悉 yield return 的工作原理:

IEnumerator MessageOuter() {
    Console.WriteLine("outer 1");
    var inner = MessageInner();
    Console.WriteLine("outer 2");
    return inner;
}
IEnumerator MessageInner() {
    Console.WriteLine("inner 1");
    yield return new WaitForSeconds(1);
    Console.WriteLine("inner 2");
    yield return new WaitForSeconds(1);
    Console.WriteLine("inner 3");
}
void Start() {
    Console.WriteLine("start 1");
    var outer = MessageOuter();
    Console.WriteLine("start 2");
    StartCoroutine(outer);
    Console.WriteLine("start 3");
}
void Start()
{
    StartCoroutine(Message(i));
    StartCoroutine(Message(i));
    StartCoroutine(Message(i));
    StartCoroutine(Message(i));
}

我认为这不是您认为应该做的事情。这不会等待每个 StartCoroutine 完成并调用下一个 StartCoroutine.

事情是这样的:

第一个 StartCoroutine(Message(i)); 调用将启动 Message 函数。 一旦遇到yield return new WaitForSeconds(waitTime = 2f);行代码,它就会跳回Start()函数。

将调用下一个 StartCoroutine(Message(i)); 然后同样的事情会再次发生。

从非协程函数调用协程函数时,只要实现了yield return new WaitForSecondsyield return null;yield return,无论什么YieldInstruction,执行将 return 到调用 StartCoroutine 函数的非协程函数,并继续执行其他代码。

要让协程等待另一个协程完成,请从另一个协程函数调用 StartCoroutine(Message(i)); 函数。这将允许您 yield 每个协程函数调用。这称为链接协程。

要链接或yield协程函数调用,只需将yield return放在StartCoroutine函数前面即可。 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
    }
}

现在,每个 StartCoroutine(Message(i)); 调用都会等到第一个调用完成。您始终可以使用 boolean 变量来执行此操作,但是 yield 调用 StartCoroutine 会更好。