简体   繁体   English

如何理解这个Unity协程?

[英]How to understand this Unity Coroutine?

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

The result is 结果是

Starting 0
WaitAndPrint 5.010554
Done 5.010554

I have two questions? 我有两个问题?

First, How to understand the return value of function Start(). 首先,如何理解函数Start()的返回值。 I used to see the return value of Start() is void. 我曾经看到Start()的返回值是空的。 And in my view, Start() only executes once (one frame) by Unity, but yield return seems make Start() function execute in two frames; 在我看来,Start()仅由Unity执行一次(一帧),但是收益回报似乎使Start()函数在两帧中执行;

Second, I am also confused by the result. 其次,我也对结果感到困惑。 I think the result should be 我认为结果应该是

Starting 0
Done 5.010554
WaitAndPrint 5.010554

Because StartCoroutine() starts the function WaitAndPrint(). 因为StartCoroutine()启动函数WaitAndPrint()。 In function WaitAndPrint(), yield return makes this function pause in this frame and return to Start(). 在WaitAndPrint()函数中, yield return使此函数在此帧中暂停并返回Start()。 Then Start() continues going on and prints "Done xxxxx". 然后Start()继续进行,并显示“ Done xxxxx”。 After 5 seconds, WaitAndPrint() resume and prints "WaitAndPrint xxxxx". 5秒后,WaitAndPrint()恢复并打印“ WaitAndPrint xxxxx”。

Where am I wrong? 我哪里错了?

Here's how I understand this result : 这是我对这个结果的理解:

The Start() function is called once by Unity and prints "Started". Start()函数由Unity调用一次,并显示“已启动”。

Then the following line does two things : 然后,以下代码行做了两件事:

yield return StartCoroutine (WaitAndPrint ());
  • it starts the WaitAndPrint() coroutine 它启动了WaitAndPrint()协程
  • it waits for it to be over before continuing in the Start() coroutine. 它等待结束,然后再继续执行Start()协程。

The WaitAndPrint() coroutine will do its stuff : WaitAndPrint()协程将完成其工作:

  • Wait for 5 seconds 等待5秒钟
  • Print "WaitAndPrint" + time 打印“ WaitAndPrint” +时间

Then the Start() coroutine will resume and print "Done" + time. 然后,Start()协程将恢复并显示“完成” +时间。

This is why 这就是为什么

print ("WaitAndPrint" + Time.time);

is printed before : 在之前打印:

print ("Done " + Time.time);

Also, you should edit your post, it misses a space in the first result : 另外,您应该编辑您的帖子,它在第一个结果中会丢失空格:

WaitAndPrint5.010554

Should be 应该

WaitAndPrint 5.010554

Sorry if it's not clear, it's my first time answering on StackOverflow, hope it helped ! 抱歉,如果不清楚,这是我第一次在StackOverflow上回答,希望对您有所帮助!

When you call yield return the control is taken by Unity. 当您调用yield return ,控件将由Unity控制。

When you start a Coroutine Unity will take the IEnumerator returned by the method and will call MoveNext on the IEnumerator returned. 当您启动一个Coroutine Unity将采用该方法返回的IEnumerator ,并在返回的IEnumerator上调用MoveNext

Based on the type of object and on the values in the object Unity will decide what to do. 根据对象的类型和对象中的值,Unity将决定要做什么。

In you case in the Start method the yield statement return another IEnumerator so Unity will not call MoveNext on the Start returned object until the second IEnumerator finishes. Start方法中, yield语句返回另一个IEnumerator因此Unity不会在第二个IEnumerator完成之前在Start返回的对象上调用MoveNext

In WaitAndPrint the first MoveNext returns a WaitForSeconds object, based on that Unity decides that it will not call MoveNext on in until 5 seconds have passed. WaitAndPrint ,第一个MoveNext返回一个WaitForSeconds对象,基于Unity决定,直到经过5秒钟,它调用MoveNext After 5 seconds it calls MoveNext again and the rest of the method is executed, which is just this line 5秒后,它再次调用MoveNext ,然后执行该方法的其余部分,即此行

print ("WaitAndPrint" + Time.time);

As the IEnumerator returned by yield return StartCoroutine (WaitAndPrint ()); 作为由yield return StartCoroutine (WaitAndPrint ());IEnumerator返回yield return StartCoroutine (WaitAndPrint ()); reached its end it will call MoveNext on the IEnumerator that was returned by Start , this in turn will execute what ever is left of Start : 到达其末尾时,它将在Start返回的IEnumerator上调用MoveNext ,这将执行Start剩下的内容:

print ("Done " + Time.time);

Hope this is clear enough :) 希望这足够清楚:)

IEnumerators are iterator blocks, they dont necessarily execute for 1 frame, when you put a yield return , you essentially are telling it to iterate over multiple frames. IEnumerators是迭代器块,它们不一定要执行1帧,当您放置yield return ,您实际上是在告诉它迭代多个帧。

When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained. 在迭代器方法中到达yield return语句时,将返回expression,并保留代码中的当前位置。

Instead of IEnumerators you can "nearly" always use Invoke method. 代替IEnumerators,您可以“几乎”始终使用Invoke方法。 Try to work with that one and your life will be easier :) 尝试与那个人一起工作,您的生活会更轻松:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM