刚了解Unity的时候,对协程的执行顺序就很懵逼,只会用协程来完成一些简单的功能实现,但是硬扣逻辑的话,还是说不上来,昨天刷到了一篇前辈的文章才让我有点恍然大明白的感觉。
前辈的文章:https://blog.csdn.net/tkokof1/article/details/11842673
生命周期函数
关于生命周期函数,相信所有接触了Unity的程序员都会了解,网上也有很多的图解,在此借用一下别人整理的图。
return null的协程
可以看到,在GameLogic部分对协程中挂起的条件进行了判断。
也就是说,协程顺序为:
(当前帧为第1帧)
第1帧在start中开启协程,执行协程(自上而下),遇到yield return null 将后面的内容挂 起。
这时继续执行第1帧剩下的东西直到第1帧Update执行结束,这时对挂起的协程进行判断 是否满足return条件,
满足则在第2帧Update之后,在LateUpdate前执行协程中yield return 以后的代码;
不满足条件则继续执行第1帧的LateUpdate。
第2帧同第1帧相同。
实测一下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
int i = 0;//update中判断次数的变量
private void Start()
{
Debug.Log("start 1");
//开启协程1
StartCoroutine(Test());
Debug.Log("start 2");
}
private void Update()
{
Debug.Log("第" + ++i + "帧开始");
}
private void LateUpdate()
{
Debug.Log("第" + i + "帧结束");
}
IEnumerator Test()
{
Debug.Log("协程1第一次");
//挂起时机
yield return null;
Debug.Log("协程1第二次");
}
}
在Unity中的运行结果:
可以看到,协程运行到一半在第一帧被挂起,第二帧Update执行完后满足条件继续执行。
yield return StartCoroutine()
了解完了return null,来看一下return StartCoroutine;
public class NewBehaviourScript : MonoBehaviour {
int i = 0;
private void Start()
{
Debug.Log("start 1");
StartCoroutine(Test());
Debug.Log("start 2");
}
private void Update()
{
Debug.Log("第" + ++i + "帧开始");
}
private void LateUpdate()
{
Debug.Log("第" + i + "帧结束");
}
IEnumerator Test()
{
Debug.Log("协程1第一次");
yield return StartCoroutine(Test2());
Debug.Log("协程1第二次");
}
IEnumerator Test2()
{
Debug.Log("协程2第一次");
yield return null;
Debug.Log("协程2第二次");
}
}
直接上运行结果:
原理都是一样的,执行完yield return 后挂起(注意不是遇到就挂起,而是执行),在每一帧的update与lateupdate之间对挂起的内容进行判断,满足则继续执行被挂起的协程的剩余部分。
更好的体现出了协程是单线程的概念。从头到尾都是在循环的执行,只有一根运行管道,没有多线程那么多安全的问题。