• C#中的yield return与Unity中的Coroutine(协程)(下)


    Unity中的Coroutine(协程)

    估计熟悉Unity的人看过或者用过StartCoroutine()

    假设我们在场景中有一个UGUI组件, Image:

    将以下代码绑定到Image

     1 using UnityEngine;
     2 using System.Collections;
     3 using System.Threading;
     4 using UnityEngine.UI;
     5 
     6 public class CoroutineDemo : MonoBehaviour {
     7 
     8     // Use this for initialization
     9     void Start () {
    10     
    11         Debug.Log (Thread.CurrentThread.Name + ": Start begin. fCount=" +  + Time.renderedFrameCount);
    12 
    13 
    14         this.StartCoroutine (exeuteCoroutine());
    15     }
    16     
    17     // Update is called once per frame
    18     void Update () {
    19         
    20         Debug.Log (Thread.CurrentThread.Name + ": Update(): fCount=" + Time.renderedFrameCount);
    21     }
    22 
    23      
    24     public IEnumerator exeuteCoroutine(){
    25         Debug.Log (Thread.CurrentThread.Name + ": Before yield return A, fCount=" + Time.renderedFrameCount);
    26         //yield return new WaitForSeconds(1);
    27         yield return "A";
    28 //        yield return "C";
    29 //        yield return "D";
    30         Debug.LogError (Thread.CurrentThread.Name + ": After yield return A, fCount=" + Time.renderedFrameCount);
    31     }
    32 
    33     IEnumerator LoadImage()
    34     {
    35         WWW www=new WWW("http://pic89.nipic.com/file/20160211/22571617_214730734684_2.jpg");
    36         Image img = this.gameObject.GetComponent<Image> ();
    37 
    38         Debug.Log("Before yield return: " + www.url + " is done? " + www.isDone + ", rf=" + Time.renderedFrameCount);
    39 
    40         yield return www;
    41 
    42         Debug.Log("After yield return, " + www.url + " is done? " + www.isDone + ", rf=" + Time.renderedFrameCount);
    43         Rect spriteRect = new Rect (0, 0, www.texture.width, www.texture.height);
    44         Sprite imageSprite = Sprite.Create (www.texture, spriteRect, new Vector2 (0.5f, 0.5f));
    45         img.sprite = imageSprite;
    46 
    47     }
    48 }
    View Code

    运行之后日志输出(Error 日志是为了明显,才这么打的):

     

    fCount 代表的是当前已经渲染的帧数,发现, yield return 之后的代码, 是在yield return 之后的一帧执行的。

    如果yield return 之后换成 new WaitForSeconds(1); yield之后的代码就在1秒后执行。

    看一下MonoBehaviour的生命周期:

    发现, 在StartCortinue()传入的方法中, 可以yield return 的类型有:

    yield return null;

    yield return WaitForSeconds(); (实际上, 继承自 YieldInstruction的都可以)

    yield return WWW;

    如果将例子中的代码改成加载图片:

    1     void Start () {  
    3         Debug.Log (Thread.CurrentThread.ManagedThreadId + ": Start begin. fCount=" +  + Time.renderedFrameCount);
    6         this.StartCoroutine (LoadImage());
    7     }
     1     IEnumerator LoadImage()
     2     {
     3         WWW www=new WWW("http://pic89.nipic.com/file/20160211/22571617_214730734684_2.jpg");
     4         Image img = this.gameObject.GetComponent<Image> ();
     5 
     6         Debug.Log("Before yield return: " + www.url + " is done? " + www.isDone + ", rf=" + Time.renderedFrameCount);
     7 
     8         yield return www;
     9 
    10         Debug.Log("After yield return, " + www.url + " is done? " + www.isDone + ", rf=" + Time.renderedFrameCount);
    11         Rect spriteRect = new Rect (0, 0, www.texture.width, www.texture.height);
    12         Sprite imageSprite = Sprite.Create (www.texture, spriteRect, new Vector2 (0.5f, 0.5f));
    13         img.sprite = imageSprite;
    14 
    15     }

    通过输出日志, 你会发现, yield return www;之后的代码, 是在www.isDone之后, 也就是图片加载完毕之后才执行的!

    Before yield return: http://pic89.nipic.com/file/20160211/22571617_214730734684_2.jpg is done? False, rf=1
    UnityEngine.Debug:Log(Object)
    <LoadImage>c__Iterator6:MoveNext() (at Assets/Scripts/CoroutineDemo.cs:38)
    UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
    CoroutineDemo:Start() (at Assets/Scripts/CoroutineDemo.cs:14)
    
    After yield return, http://pic89.nipic.com/file/20160211/22571617_214730734684_2.jpg is done? True, rf=34
    UnityEngine.Debug:Log(Object)
    <LoadImage>c__Iterator6:MoveNext() (at Assets/Scripts/CoroutineDemo.cs:42)

    总结:

    yield return 搭配上WaitForSecond, WWW, 可以达到延时执行的效果。

    但是, 特别注意的是, StartCoroutine()并没有开启新的线程来执行, 还是执行在与Start(), Update()相同的主线程中!

  • 相关阅读:
    idea拉取git项目并创建为maven项目(新创建github项目)
    寒假学习进度-4
    寒假学习进度-3
    寒假学习进度-2
    寒假学习进度-1
    面向对象设计原则
    Servlet中生成json文件,echarts模板调用
    Mapreduce--数据清洗
    Tutorial 06_MapReduce实例WordCount
    爬虫学习-入门
  • 原文地址:https://www.cnblogs.com/vivid-stanley/p/5274240.html
Copyright © 2020-2023  润新知