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

Unity中的Coroutine(协程)

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

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

将如下代码绑定到Imageurl

 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 日志是为了明显,才这么打的):spa

 

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

若是yield return 以后换成 new WaitForSeconds(1); yield以后的代码就在1秒后执行。3d

看一下MonoBehaviour的生命周期:日志

 

 

发现, 在StartCortinue()传入的方法中, 能够yield return 的类型有:code

yield return null;协程

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

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()相同的主线程中!

相关文章
相关标签/搜索