协程的概念
Unity协程(Coroutine),可以用来实现一些延时处理的需求,C#中通过yield return语句配合可以中断执行,延时一定时间后从中断处继续执行。
协程不是线程,协程还是在主线程里执行的。所以就不需要考虑同步和锁的问题。
原理
Unity的协程是一个扩展成支持嵌套的迭代器(IEnumator)。
它将c# IEnumerator封装为Coroutine对象,记录了该协程的上一级协程是谁,当这个协程执行完成,会继续执行上一级协程。
当Unity Coroutine调用IEnumerator的MoveNext返回一个新Coroutine时,Unity设置新对象的上级Coroutine为当前Coroutine,同时将新Coroutine压入队列,通过此实现嵌套。
然后Unity在主线程中定时检测当前每个等待的Coroutine,满足条件则执行。
用法
yield
之前学过javascript的异步,里面也有yield关键字,都是暂停执行当前的函数,先去执行yield后面的语句(可以是一个函数),然后执行完毕会直接返回,如果有多个yield就需要手动调用next()
进行迭代。在js里面就以这种方式实现Ajax异步操作的顺序执行,在Unity里面则是实现类似于子线程(注意只是类似!),它的执行也是顺序执行的。
yield语句用于暂停协程的执行(暂停一帧,跳出协程),yield return 的值决定什么时候恢复协程的执行。
yield语句的返回有如下类型:
yield return null;//下一帧再继续往下执行
yield return new WaitForFixedUpdate();//等到下一次调用FixedUpdate再往下执行
yield return new WaitForSceonds(n);//等待n秒再往下执行
yield return StartCoroutine(Method);//开启另一个协程,直到Method执行完毕再往下执行
yield return new WaitForEndOfFrame();//等到该帧结束再往下执行
yield return WWW;//等待资源加载完成再往下执行
yield break;//结束协程
函数
启动一个协程
StartCoroutine("tmp");
StartCoroutine("tmp","value");
StartCoroutine(tmp());
//推荐使用`StartCoroutine(tmp());
//因为传递方法名需要用到反射机制,影响性能。
终止协程。
StopAllCoroutines();//关闭所有协程注意,这只会终止在调用该方法的对象中
StopCoroutine("tmp");//注意开启协程传递字符,关闭也要传递字符
StopCoroutine(tmp());
//注意
this.enabled = false; //会停止update()运行,但是协程还在运行
this.gameObject.SetActive(false); //update和协程都会停止运行
实例
如果遇到一些执行顺序的问题,可以直接看官方文档函数执行顺序的流程图。
http://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg
private void Start ()
{
//启动销毁计时器协程
StartCoroutine(DestroyAfter ());
}
private IEnumerator DestroyAfter ()
{
//等待设定的时间后销毁对象
yield return new WaitForSeconds (5);
Destroy (gameObject);
}