• Unity3D之协程(Coroutines & Yield )


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

    [csharp] view plaincopyprint?
     
    1. <span style="font-size:18px;">private int state = 0;  
    2. void Update()  
    3. {  
    4.         if (state == 0)   
    5.         {  
    6.                 //做步骤0  
    7.                 state = 1;  
    8.                 return;  
    9.         }  
    10.         if (state == 1)   
    11.         {  
    12.                 // 做步骤1  
    13.                 state = 2;  
    14.                 return;  
    15.         }  
    16.         // ...  
    17. } </span>  


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


    [csharp] view plaincopyprint?
     
    1. <span style="font-size:18px;">while(true) {  
    2.         // 做步骤0  
    3.         yield return 0;  
    4.          // 等待一帧  
    5.         // 做步骤1  
    6.         yield return 2;  
    7.          // 等待两帧  
    8.         // ...  
    9. } </span>  


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

    [csharp] view plaincopyprint?
     
    1. <span style="font-size:18px;">  // do something  
    2.   yield return WaitForSeconds  (5.0);  
    3.   //等待5秒  
    4.   // do something more...  </span>  

    你可以入栈并连接协程.


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


    [csharp] view plaincopyprint?
     
    1. <span style="font-size:18px;">Do ();  
    2. Console.WriteLine("This is printed immediately");  
    3. IEnumerator  Do ()  
    4. {  
    5.     Console.WriteLine("Do now");  
    6.     yield return new WaitForSeconds  (2);        
    7.     Console.WriteLine("Do 2 seconds later");  
    8. } </span>  


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


    [csharp] view plaincopyprint?
     
    1. <span style="font-size:18px;">// 启动协程  
    2. yield return StartCoroutine("Do");  
    3. Console.WriteLine("Also after 2 seconds");  
    4. Console.WriteLine ("这个print将在Do协程执行完以后显示。");  
    5. IEnumerator  Do ()  
    6. {        
    7. Console.WriteLine("Do now");  
    8. yield return new WaitForSeconds  (2);  
    9. Console.WriteLine("Do 2 seconds later");  
    10. }  
    11. </span>  


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


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


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


    [csharp] view plaincopyprint?
     
    1. <span style="font-size:18px;">void Start () {  
    2.   
    3.   
    4.         print("Starting:" + Time.time);  
    5.   
    6.   
    7.         StartCoroutine(WaitAnPrint(2.0F));  
    8.   
    9.   
    10.         print("Before WaiAndPrint:" + Time.time);  
    11.   
    12.   
    13.     }  
    14.   
    15.   
    16. IEnumerator WaitAndPrint(float waitTime)  
    17.   
    18.   
    19.     {  
    20.   
    21.   
    22.         yield return new WaitForSeconds(waitTime);  
    23.   
    24.   
    25.         print("WaitAndPrint:" + Time.time);      
    26.   
    27.   
    28.     }  
    29. </span>  


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


    Starting:0


    Before WaiAndPrint:0


    WaitAndPrint:2.12291


    例2:


    [csharp] view plaincopyprint?
     
    1. <span style="font-size:18px;">IEnumerator Start()  
    2.   
    3.   
    4.     {  
    5.   
    6.   
    7.         print("starting:" + Time.time);  
    8.   
    9.   
    10.         yield return StartCoroutine(WaitAndPrint(2.0F));  
    11.   
    12.   
    13.         print("done:" + Time.time);  
    14.   
    15.   
    16.     }  
    17.   
    18.   
    19. IEnumerator WaitAndPrint(float waitTime)  
    20.   
    21.   
    22.     {  
    23.   
    24.   
    25.         yield return new WaitForSeconds(waitTime);  
    26.   
    27.   
    28.         print("WaitAndPrint:" + Time.time);      
    29.   
    30.   
    31.     }</span>  



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


    starting:0

    WaitAndPrint:2.00315

    done:2.00315
    [csharp] view plaincopyprint?
     
    1. <pre name="code" class="csharp"><pre name="code" class="csharp"><pre name="code" class="csharp"><p></p><pre></pre>  
    2. <pre></pre>  
    3. <pre></pre>  
    4. <pre></pre>  
    5. <pre></pre>  
    6. <pre></pre>  
    7. <pre></pre>  
    8. <pre></pre>  
    9. <pre></pre>  
    10. <pre></pre>  
    11. <pre></pre>  
    12. <pre></pre>  
    13. <pre></pre>  
    14. <pre></pre>  
    15. <pre></pre>  
    16. <pre></pre>  
    17. <pre></pre>  
    18. <pre></pre>  
    19. <pre></pre>  
    20.   
    21. </pre></pre></pre>  
     
  • 相关阅读:
    Java编程思想读书笔记 第十章 内部类
    利用lambda和条件表达式构造匿名递归函数
    概率论与数理统计-课程小报告
    leetcode226 翻转二叉树
    leetcode199 二叉树的右视图
    leetcode114- 二叉树展开为链表
    leetcode145 二叉树的后序遍历 特别注意迭代
    leet144 二叉树的前序遍历
    leetcode113 路径总和2 特别关注
    leetcode 112 路径总和 特别关注
  • 原文地址:https://www.cnblogs.com/xpvincent/p/3214388.html
Copyright © 2020-2023  润新知