在进行主任务的过程中我们需要一个对资源消耗极大的操作时,如果在一帧中实现这一的操作,游戏就会变得十分卡顿,这个时候,我们就可以通过协程,在一定帧内完成该工作的处理,同时不影响主任务的进行。
实现原理
协程依旧是在主线程中进行,通过关键字IEnumerator
来定义一个迭代方法,在迭代方法中使用yield
关键字,可以使协程的运行暂停、记录下一次启动的时间与位置等。
在程序中通过StartCoroutine
来开启一个协程,StopCoroutine
来关闭一个协程。
注意不是IEnumerable
,它是在IEnumerator
基础上的一个封装接口,有一个GetEnumerator()
方法返回IEnumerator
。
使用方法
StartCoroutine
的重载:
StartCoroutine(string methodName)
:通过方法的名字来开启协程
StartCoroutine(string methodName,object values)
:带形参的情况下,通过方法的名字来开启协程
StartCoroutine(IEnumerator routine)
:通过指定的方法调用协程
StopCoroutine
的重载:
StopCoroutine(string methodName)
:通过方法的名字来关闭协程
StopCoroutine(IEnumerator routine)
:通过指定的方法来关闭协程
StopCoroutine(Coroutine routine)
:通过指定的协程来关闭协程
yield
在生命周期中位于Update
与LateUpdate
之间,在迭代方法中有不少使用方式:
yield return null;
暂停协程等待下一帧继续执行
yield return 数字;
暂停协程等待下一帧继续执行
yield return new WaitForFixedUpdate();
等到下一个固定帧数更新
yield return new WaitForSeconds(时间);
等待规定时间后继续执行
yield return new WaitForEndOfFrame();
等到所有相机画面渲染完毕后更新
yield return StartCoroutine("协程方法名");
开启一个协程
yield break;
跳出协程对应方法
实际应用
如果某一时刻需要使用Update
读取一个列表,这样一般需要一个循环去遍历列表,这样每帧的代码执行量就比较大,就可以将这样的执行放置到协程中来处理:
public List<int> nums = new List<int> { 1, 2, 3, 4, 5, 6 };
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(PrintNum(nums));
}
}
//通过协程分帧处理
IEnumerator PrintNum(List<int> nums)
{
foreach (int i in nums)
{
Debug.Log(i);
yield return null;
}
StopCoroutine(PrintNum(nums));
}