查看: 2221|回复: 2
打印 上一主题 下一主题

[经验分享] Unity3D之协程(Coroutines & Yield )

[复制链接]

1557

主题

1

听众

1万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
454
精华
31

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2013-10-12 15:21:40 |只看该作者 |倒序浏览
写游戏代码,往往最终需要代码为连续的事件.结果会像这样:
[它可以实现将一段程序延迟执行或者将其各个部分分布在一个时间段内连续执行。]
[csharp] view plaincopyprint?


  • <span style="font-size:18px;">private int state = 0;  
  • void Update()  
  • {  
  •         if (state == 0)   
  •         {  
  •                 //做步骤0  
  •                 state = 1;  
  •                 return;  
  •         }  
  •         if (state == 1)   
  •         {  
  •                 // 做步骤1  
  •                 state = 2;  
  •                 return;  
  •         }  
  •         // ...  
  • } </span>  


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


  • <span style="font-size:18px;">while(true) {  
  •         // 做步骤0  
  •         yield return 0;  
  •          // 等待一帧  
  •         // 做步骤1  
  •         yield return 2;  
  •          // 等待两帧  
  •         // ...  
  • } </span>  

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


  • <span style="font-size:18px;">  // do something  
  •   yield return WaitForSeconds  (5.0);  
  •   //等待5秒  
  •   // do something more...  </span>  

你可以入栈并连接协程.
这个例子将执行Do,但是do函数之后的print指令会立刻执行.
[csharp] view plaincopyprint?


  • <span style="font-size:18px;">Do ();  
  • Console.WriteLine("This is printed immediately");  
  • IEnumerator  Do ()  
  • {  
  •     Console.WriteLine("Do now");  
  •     yield return new WaitForSeconds  (2);        
  •     Console.WriteLine("Do 2 seconds later");  
  • } </span>  

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


  • <span style="font-size:18px;">// 启动协程  
  • 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");  
  • }  
  • </span>  

任何事件处理程序都可以是协同程序 。
注意你不能在Update或FixedUpdate函数内使用yield,但是你能使用 StartCoroutine  开始一个函数.
查看 YieldInstruction , WaitForSeconds , WaitForFixedUpdate , Coroutine  and MonoBehaviour.StartCoroutine  可以获得更多使用yield的信息.
yield return可以看做是一种特殊的return,会返回到父类继续执行,但是yield return后面的类型或方法会有一个执行条件,当条件满足时会回调包含yield的子函数,例如下面代码
例1:
[csharp] view plaincopyprint?


  • <span style="font-size:18px;">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);      
  •   
  •   
  •     }  
  • </span>  

在执行yield return new WaitForSeconds(waitTime)时暂停的条件没有满足,故返回到start函数中继续执行,直到满足条件后再回调WaitAndPrint,所以输出为:
Starting:0
Before WaiAndPrint:0
WaitAndPrint:2.12291
例2:
[csharp] view plaincopyprint?


  • <span style="font-size:18px;">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);      
  •   
  •   
  •     }</span>  


因为start为顶级函数,所以会阻塞在这里,直到StartCoroutine(WaitAndPrint(2.0F))执行完毕,输出为:
starting:0
WaitAndPrint:2.00315
done:2.00315
[csharp] view plaincopyprint?


  • <pre name="code" class="csharp"><pre name="code" class="csharp"><pre name="code" class="csharp"><p></p><pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  • <pre></pre>  
  •   
  • </pre></pre></pre>  


分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

nts    

3

主题

1

听众

743

积分

初级设计师

Rank: 3Rank: 3

纳金币
7
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2013-10-13 11:14:15 |只看该作者
这个应该是C#专用吧
回复

使用道具 举报

2

主题

1

听众

1143

积分

助理设计师

Rank: 4

纳金币
350
精华
0
板凳
发表于 2013-10-28 10:57:07 |只看该作者
感谢楼主分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-4-28 18:02 , Processed in 0.086878 second(s), 32 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部