Unity3D之协程(Coroutines & Yield )

时间:2021-05-21 23:35:20
写游戏代码,往往最终需要代码为连续的事件.结果会像这样:
[它可以实现将一段程序延迟执行或者将其各个部分分布在一个时间段内连续执行。]

private int state = 0;
void Update()
{
        if (state == 0) 
        {
                //做步骤0
                state = 1;
                return;
        }
        if (state == 1) 
        {
                // 做步骤1
                state = 2;
                return;
        }
        // ...
} 


往往使用yield语句更为方便.yield语句是一个特殊的返回类型,它确保函数从yield语句的下一行继续执行.


while(true) {
        // 做步骤0
        yield return 0;
         // 等待一帧
        // 做步骤1
        yield return 2;
         // 等待两帧
        // ...
} 


你也可以传递时间值到yield语句,Update函数会在yield结束后执行下一语句.

  // do something
  yield return WaitForSeconds  (5.0);
  //等待5秒
  // do something more...  

你可以入栈并连接协程.


这个例子将执行Do,但是do函数之后的print指令会立刻执行.


Do ();
Console.WriteLine("This is printed immediately");
IEnumerator  Do ()
{
	Console.WriteLine("Do now");
	yield return new WaitForSeconds  (2);      
	Console.WriteLine("Do 2 seconds later");
} 


这个例子将执行Do,并等待,直到Do完成再执行其他语句.【注:这里的等待是把线程时间交给其他任务,而不是阻塞式等待】


// 启动协程
yield return StartCoroutine("Do");
Console.WriteLine("Also after 2 seconds");
Console.WriteLine ("这个print将在Do协程执行完以后显示。");
IEnumerator  Do ()
{      
Console.WriteLine("Do now");
yield return new WaitForSeconds  (2);
Console.WriteLine("Do 2 seconds later");
}


任何事件处理程序都可以是协同程序 。


注意你不能在Update或FixedUpdate函数内使用yield,但是你能使用 StartCoroutine  开始一个函数.


查看 YieldInstruction , WaitForSeconds , WaitForFixedUpdate , Coroutine  and MonoBehaviour.StartCoroutine  可以获得更多使用yield的信息.
yield return可以看做是一种特殊的return,会返回到父类继续执行,但是yield return后面的类型或方法会有一个执行条件,当条件满足时会回调包含yield的子函数,例如下面代码
例1:


void Start () {


        print("Starting:" + Time.time);


        StartCoroutine(WaitAnPrint(2.0F));


        print("Before WaiAndPrint:" + Time.time);


    }


IEnumerator WaitAndPrint(float waitTime)


    {


        yield return new WaitForSeconds(waitTime);


        print("WaitAndPrint:" + Time.time);    


    }


在执行yield return new WaitForSeconds(waitTime)时暂停的条件没有满足,故返回到start函数中继续执行,直到满足条件后再回调WaitAndPrint,所以输出为:


Starting:0


Before WaiAndPrint:0


WaitAndPrint:2.12291


例2:


IEnumerator Start()


    {


        print("starting:" + Time.time);


        yield return StartCoroutine(WaitAndPrint(2.0F));


        print("done:" + Time.time);


    }


IEnumerator WaitAndPrint(float waitTime)


    {


        yield return new WaitForSeconds(waitTime);


        print("WaitAndPrint:" + Time.time);    


    }



因为start为*函数,所以会阻塞在这里,直到StartCoroutine(WaitAndPrint(2.0F))执行完毕,输出为:


starting:0

WaitAndPrint:2.00315

done:2.00315