【问题标题】:Unity - IEnumerator's yield return nullunity - IEnumerator 的产量返回 null
【发布时间】:2017-06-02 21:05:35
【问题描述】:

我目前正在尝试在 Unity 的上下文中理解 IEnumerator 和 Coroutine,并且对“yield return null”的执行情况不太有信心。目前我相信它基本上会暂停并等待下一帧,在下一帧中它会再次执行 while 语句。

如果我省略了“yield return null”,那么该对象似乎会立即移动到它的目的地,或者可能会“跳过很多帧”。所以我想我的问题是这个while循环中的“yield return null”函数是如何实现的,为什么需要它。

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

IEnumerator Move(){

    while (a > 0.5f){

        ... (moves object up/down)

        yield return null; // <---------
    }

    yield return new WaitForSeconds(0.5f);

    .... (moves object up/down)

    StartCoroutine(Move());
}

【问题讨论】:

  • 我自己对协程并不熟悉,但我的猜测是它们每帧(或其他)会运行一次,yield return 基本上是说“等到下一次更新再继续”的快捷方式”。如果没有它,while 循环将一直运行到一次更新完成,这就是为什么没有它时对象会立即移动。
  • @Abion47,所以如果说要进行 40 次迭代,并且我们在其间添加了 yield return null,这是否意味着它需要 40 帧才能完成迭代?
  • 如果是这样,那么运动将取决于 fps?如果是 60 fps,那么它会在不到一秒的时间内到达目标,如果是 20fps,它会在 2 秒内到达目标?
  • @supernatural 基本上,是的。

标签: c# unity3d yield coroutine ienumerator


【解决方案1】:

程序将开始循环,如果您没有 yield,它只会在同一帧内运行所有迭代。 如果您有数百万次迭代,那么它很可能会阻塞您的程序,直到所有迭代都完成然后继续。

在创建协程时,Unity 会将其附加到 MonoBehaviour 对象。它将首先在调用 StartCoroutine 时运行,直到达到 yield。然后它将从协程返回并根据产量将其放入堆栈。如果您产生 null,那么它将在下一帧再次运行。协程可以返回许多不同的 YieldInstruction,您可以阅读更多关于它们的信息here and through the related links

一旦协程产生,主线程继续运行。在下一帧,Unity 将找到堆叠的协程,并从它们在 yield 中断的地方调用它们。 如果您的协程永远不会超出范围,那么您基本上创建了一个更新方法。

协程的目的是在不阻塞程序的情况下执行可以跨越一段时间的操作。

重要事实:这不是多线程。

【讨论】:

  • 另一个问题。在下一个循环中,Unity 是先运行 yield 协程,等待它再次 yield 还是完成后再执行 update 方法,还是先执行 update 方法?
  • 查看链接,显示更新和动画之间处理协程。因此它将首先运行您的更新,然后继续检查是否有任何待处理的协程。docs.unity3d.com/Manual/ExecutionOrder.html
【解决方案2】:

你是对的。 yield return null 将等到下一帧,然后继续执行。在您的情况下,它将在下一帧检查您的 while 循环的条件。

“为什么这是必要的”可能是因为您希望对象每帧移动一个输入。如果没有yield return null,它只会在一帧中通过while循环执行。

更重要的是:看起来你想Update 每一帧并调整位置。您可以轻松地使用Update ()。 Unity 将在活动脚本上的每一帧调用此函数。

【讨论】:

    猜你喜欢
    • 2014-02-22
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多