协程是什么
简单来说,协程就是Unity官方提供的一个类似于C#中多线程的功能。可以在组件中使用(即继承与monhaviour),为什么不直接用C#多线程,别问,问就是不安全。
协程有什么用(为什么要用携程)
可以实现异步加载,达到多线程的效果(实际上并不是多线程)。具体用法可以参考我的这一篇文章Unity使用协程实现异步下载图片并加载
练习题与讲解
第一题
void Start()
{
print("Starting " + Time.time);//------1
StartCoroutine(WaitAndPrint(2));//-----2
print("Done " + Time.time);//----------3
}
IEnumerator WaitAndPrint(float waitTime)
{
yield return new WaitForSeconds(waitTime);//----------4
print("WaitAndPrint " + Time.time);//-----------------5
}
答案是
1 2 4 3 5
思路讲解:
1先执行,然后执行2,2是协程,即进入协程方法内部开启协程执行4,结果遇到yield return,需要等2秒再继续执行该协程下的方法,遂暂时退出该协程,执行主线程的方法3,等待协程条件到达,返回协程执行5。
流程图:字丑见谅
软件运行结果:
第二题
IEnumerator Start()
{
print("Starting " +Time.time);//---------------------------1
yield return StartCoroutine(WaitAndPrint(2.0F));//---------2
print("Done " +Time.time);//-------------------------------3
}
IEnumerator WaitAndPrint(float waitTime)
{
yield return new WaitForSeconds(waitTime);//--------------4
print("WaitAndPrint " + Time.time);//---------------------5
}
答案是
1 2 4 5 3
思路讲解:
先执行1没有什么问题,然后执行2,进入协程,但是2是带有yield return的,这代表需要等协程执行完,才可以继续执行该线程下的剩余内容,于是执行4,等待2秒字后执行5,协程内部执行完毕,返回主线程执行3。
注意点:这里有个迷惑的点,主线程中用了yield return,这个其实是错误的用法,协程本意是实现类似多线程的效果,这里却让主线程卡住,通常不会这么用。
流程图:
软件运行结果:
第三题
IEnumerator Start() {
yield return StartCoroutine (Wait(2.0F));
print("1StartingA " +Time.time);//----------------------1
yield return StartCoroutine(WaitAndPrint(2.0F));
print("3Done " +Time.time);//---------------------------3
}
IEnumerator Wait(float waitTime) {
yield return new WaitForSeconds (waitTime);
print("2StartingB " +Time.time);//----------------------2
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("4WaitAndPrint " + Time.time);//------------------4
}
答案
2 1 4 3
思路讲解
程序上来就使用了带有yield return的协程,需要等协程完成之后才能继续运行,因此进入wait方法中等2秒调用2,协程完成后返回主线程执行1,然后遇到第二个带有yield return 协程,等待协程中的4完成之后再次返回主线程,然后执行3.
流程图:
软件执行结果:
第四题
void Start() {
StartCoroutine (Wait(2.0F));
print("1StartingA" +Time.time);//-------------------1
StartCoroutine(WaitAndPrint(2.0F));
print("3Done " +Time.time);//-----------------------3
}
IEnumerator Wait(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("2StartingB" +Time.time);//-------------------2
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("4WaitAndPrint " + Time.time);//--------------4
}
答案
1 3 2 4
思路讲解:
第一步开启协程,需要等待2秒才能执行2,于是返回主线程执行1,然后遇到第二个协程,需要等待2秒才能执行4,于是返回主线程执行3,两秒时间到,先开启的线程2 ,于是先完成2,然后完成4.
流程图:
软件执行结果:
第五题
void Start() {
StartCoroutine (Wait(2.0F));
print("1 Starting " +Time.time);//-----------------------1
}
IEnumerator Wait(float waitTime) {
yield return StartCoroutine(WaitAndPrint(2.0F));
print("2 Done " +Time.time);//---------------------------2
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("3 WaitAndPrint " + Time.time);//------------------3
}
答案
1 3 2
思路讲解
第一步开启协程,进入协程中发现带有yield return的另一个协程和一个方法2,方法2需要等协程运行完之后才能继续运行,于是进入第二个协程开始计时,并且返回主线程告诉自己需要等待,你先继续下去,于是执行1,两秒时间到,第二个协程运行完成,执行3,第二个协程完成之后返回上一个协程,调用2。口述比较绕,看流程图会好一点。
流程图:
软件运行结果:
第六题
IEnumerator Start() {
StartCoroutine (Wait(2.0F));
print("1 StartingA " +Time.time);//---------------------------1
yield return StartCoroutine(WaitAndPrint(2.0F));
print("3 Done " +Time.time);//--------------------------------3
}
IEnumerator Wait(float waitTime) {
yield return new WaitForSeconds (waitTime);
print("2 StartingB " +Time.time);//---------------------------2
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("4W aitAndPrint " + Time.time);//-----------------------4
}
答案
1 2 4 3
流程图与思路讲解:
软件运行结果:
第七题
void Start() {
StartCoroutine (Wait(2.0F));
print("1 StartingA " +Time.time);//-------------------1
}
IEnumerator Wait(float waitTime) {
yield return new WaitForSeconds (waitTime);
print("2 StartingB " +Time.time);//-------------------2
yield return StartCoroutine(WaitAndPrint(2.0F));
print("3 Done " +Time.time);//------------------------3
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("4 WaitAndPrint " + Time.time);//---------------4
}
答案
1 2 4 3
流程图与思路讲解
软件结果
第八题
void Start() {
StartCoroutine (Wait(2.0F));
print("1 StartingA " +Time.time);//-------------------------1
}
IEnumerator Wait(float waitTime) {
yield return StartCoroutine(WaitAndPrint(waitTime));
print("3 Done " +Time.time);//------------------------------3
}
IEnumerator WaitAndPrint(float waitTime) {
print("2 StartingB " +Time.time);//-------------------------2
yield return new WaitForSeconds(waitTime);
print("4 WaitAndPrint " + Time.time);//---------------------4
}
答案
2 1 4 3
思路讲解:
这一题非常的绕,先开启协程wait,进入wait发现里面还有一个协程waitAndPrint,并且需要等waitAndPrint协程完成之后才能运行3,进入waitAndPrint协程,执行2,遇到WaitForSeconds协程,等待2秒才能运行4,于是一步一步返回到主线程执行1,2秒后,时间到,执行4,WaitAndPrint协程全部完成,因为带有yield return 返回Wait 执行 3。总体顺序2 1 4 3.
流程图不好画,此处省略。
软件结果:
要点总结
使用协程需要十分注意是否有yield return 关键词修饰,如果有,则说明需要等待这个协程完成才能当前线程下的其他操作,如果没有,则可以继续操作。
PS:千万不要在主线程中使用yield return ,毫无意义,实现的和啥都不同一样是同步效果。