【问题标题】:How to understand this Unity Coroutine?如何理解这个 Unity Coroutine?
【发布时间】:2015-09-20 04:32:30
【问题描述】:
using UnityEngine;
using System.Collections;

public class CoroutineExample : MonoBehaviour
{
    IEnumerator Start ()
    {
        print ("Starting " + Time.time);
        yield return StartCoroutine (WaitAndPrint ());
        print ("Done " + Time.time);
    }

    IEnumerator WaitAndPrint ()
    {
        yield return new WaitForSeconds (5f);
        print ("WaitAndPrint " + Time.time);
    }
}

结果是

Starting 0
WaitAndPrint 5.010554
Done 5.010554

我有两个问题?

首先,如何理解函数Start()的返回值。我曾经看到 Start() 的返回值是 void。在我看来,Start() 只执行一次(一帧)Unity,但 yield return 似乎使 Start() 函数在两帧内执行;

其次,我也对结果感到困惑。我认为结果应该是

Starting 0
Done 5.010554
WaitAndPrint 5.010554

因为 StartCoroutine() 启动了 WaitAndPrint() 函数。在函数 WaitAndPrint() 中,yield return 使该函数在此帧中暂停并返回到 Start()。然后 Start() 继续进行并打印“Done xxxxx”。 5 秒后,WaitAndPrint() 恢复并 打印“WaitAndPrint xxxxx”。

我哪里错了?

【问题讨论】:

    标签: c# unity3d coroutine


    【解决方案1】:

    当您调用yield return 时,Unity 将获得控制权。

    当您启动Coroutine 时,Unity 将采用该方法返回的IEnumerator,并在返回的IEnumerator 上调用MoveNext

    Unity 会根据对象的类型和对象中的值来决定要做什么。

    在您的情况下,在 Start 方法中,yield 语句返回另一个 IEnumerator,因此在第二个 IEnumerator 完成之前,Unity 不会在 Start 返回的对象上调用 MoveNext

    WaitAndPrint 中,第一个MoveNext 返回一个WaitForSeconds 对象,基于Unity 决定在5 秒后它不会调用MoveNext。 5 秒后它再次调用MoveNext 并执行该方法的其余部分,就是这一行

    print ("WaitAndPrint" + Time.time);
    

    yield return StartCoroutine (WaitAndPrint ()); 返回的IEnumerator 结束时,它将在IEnumerator 上调用MoveNext,这是Start 返回的,这将依次执行Start 的剩余部分:

    print ("Done " + Time.time);
    

    希望这足够清楚:)

    【讨论】:

    • 根据对象的类型和对象中的值,Unity 将决定做什么。这就是重点!
    【解决方案2】:

    我是这样理解这个结果的:

    Unity 调用 Start() 函数一次并打印“Started”。

    那么下面这行做了两件事:

    yield return StartCoroutine (WaitAndPrint ());
    
    • 它启动 WaitAndPrint() 协程
    • 它会等待它结束,然后再继续 Start() 协程。

    WaitAndPrint() 协程将完成它的工作:

    • 等待 5 秒
    • 打印“WaitAndPrint”+时间

    然后 Start() 协程将恢复并打印“完成”+时间。

    这就是为什么

    print ("WaitAndPrint" + Time.time);
    

    在之前打印:

    print ("Done " + Time.time);
    

    另外,你应该编辑你的帖子,它在第一个结果中遗漏了一个空格:

    WaitAndPrint5.010554
    

    应该是

    WaitAndPrint 5.010554
    

    如果不清楚,抱歉,这是我第一次在 StackOverflow 上回答,希望对您有所帮助!

    【讨论】:

      【解决方案3】:

      IEnumerators 是迭代器块,它们不一定执行 1 帧,当您放置 yield return 时,实际上是在告诉它迭代多个帧。

      当迭代器方法中到达一个yield return语句时, 返回表达式,并保留代码中的当前位置。

      【讨论】:

        【解决方案4】:

        您可以“几乎”始终使用 Invoke 方法来代替 IEnumerators。尝试使用它,您的生活会更轻松:)

        【讨论】:

          猜你喜欢
          • 2019-09-12
          • 2021-11-25
          • 2019-08-11
          • 1970-01-01
          • 1970-01-01
          • 2011-05-06
          • 2018-03-28
          • 1970-01-01
          • 2022-06-16
          相关资源
          最近更新 更多