什么是协程?协程是用来干什么的?
什么是协程?
协同程序(coroutine),即在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行。遇到条件(yield return 语句)会挂起,直到条件满足才会被唤醒继续执行后面的代码。
协程是用来干什么的?
简单的:协程可以在不影响主线程的情况下在开启一个“协同程序”来执行系统“准备”等的一些有趣的工作!
比如说:异步加载游戏场景,异步加载网络资源等等......
协同程序的开启与终止
在Unity3D中,使用MonoBehaviour.StartCoroutine方法即可开启一个协同程序,也就是说该方法必须在MonoBehaviour或继承于MonoBehaviour的类中调用。
在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator routine)都可以开启一个线程。区别在于使用字符串作为参数可以开启线程并在线程结束前终止线程,相反使用IEnumerator 作为参数只能等待线程的结束而不能随时终止(除非使用StopAllCoroutines()方法);另外使用字符串作为参数时,开启线程时最多只能传递 一个参数,并且性能消耗会更大一点,而使用IEnumerator 作为参数则没有这个限制。
在Unity3D中,使用StopCoroutine(string methodName)来终止一个协同程序,使用StopAllCoroutines()来终止所有可以终止的协同程序,但这两个方法都只能终止该 MonoBehaviour中的协同程序。
还有一种方法可以终止协同程序,即将协同程序所在gameobject的active属性设置为false,当再次设置active为ture时,协同程 序并不会再开启;如是将协同程序所在脚本的enabled设置为false则不会生效。这是因为协同程序被开启后作为一个线程在运行,而 MonoBehaviour也是一个线程,他们成为互不干扰的模块,除非代码中用调用,他们共同作用于同一个对象,只有当对象不可见才能同时终止这两个线 程。然而,为了管理我们额外开启的线程,Unity3D将协同程序的调用放在了MonoBehaviour中,这样我们在编程时就可以方便的调用指定脚本 中的协同程序,而不是无法去管理,特别是对于只根据方法名来判断线程的方式在多人开发中很容易出错,这样的设计保证了对象、脚本的条理化管理,并防止了重 名。
协同的用法
Yield中断:(有中断就代表程序停在该处,等待yield后的时间结束再继续执行后面的语句。)
注意:
在unity C#中yield(中断)语句必须要在IEnumerator类型里。
方法的返回类型为IEnumerator。
yield不可以在Update或者FixedUpdate里使用。
这里有两种:StartCoroutine(协同工作) 和 yield return StartCoroutine(中断式的协同工作)
有yield的代表先执行完本语句(不管多长时间),或者执行完本yield方法调用,才执行后续语句。例如StartCoroutine(WaitAndPrint(2.0F)),继续执行StartCoroutine后面的语句,
没有yield的代表继续顺序执行。例如:yield return StartCoroutine(WaitAndPrint(2.0F)),代表StartCoroutine(WaitAndPrint(2.0F))函数里等待全部执行完,再执行StartCoroutine后面的语句
我们看一下官方提供的两个例子
非中断式的:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
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);
}
}
中断式的
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
IEnumerator Start() {
StartCoroutine("DoSomething", 2.0F);
yield return new WaitForSeconds(1);
StopCoroutine("DoSomething");
}
IEnumerator DoSomething(float someParameter) {
while (true) {
print("DoSomething Loop");
yield return null;
}
}
}
聪明如你,肯定能很容易的判断出两段程序的打印顺序吧
下面是那些你可以yield return 的:
null -表示暂缓一帧,在下一帧接着往下处理,也可以写成yield return 0或者yield return 1,然而,yield return num的写法其实后面的数字是不起作用的,不管为多少,表示都是在下一帧接着处理。
WaitForEndOfFrame - 等到本帧的帧末进行在进行处理
WaitForSeconds - 使协程在一定的游戏时间后执行,跟Time.timeScale是有关联的
WWW - 等待www加载完成后执行
Another coroutine - 等待其他的协同,在这种情况下,新的协同程序将在这个Yield恢复之前完成)
你还可以发出 yield break 命令,去立即停止这个协程