为什么我的 "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 WaitForSeconds
、yield 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
会更好。
我是编程的新手,我觉得这里有一个非常愚蠢的错误。但是谁能解释一下,为什么我立即只显示最后一条消息,而不是 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 WaitForSeconds
、yield 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
会更好。