c#协程
- 概:早就听闻Unity协程有必要学一手,但我还是搁置了好久,直到这个搓东西的时候被迫用了多线程发现解决不了,百度一手得知我不得不学一下协程了。在搜集了一些资料后发现知乎大佬的博文香的一批(我当场推荐:Unity协程的原理与应用 )
什么是协程
- 熟悉编程的人都知道“多线程”,如果说线程是进程的儿子,那么协程就是线程的儿子。
- 协程作为“轻量级线程”出现在我们的程序中,但实施上协程并非另外开了一个线程来执行,它仍然运行在我们的主线程上。
- Unity中的函数仅能在主线程上运行,也就是说,额外开一个线程你只能做一些简单的和Unity无关的数据计算,想要在另外一段“线程”中异步进行Unity相关操作,就得使用协程。
协程怎么用
基础使用步骤
- 第一步你需要搓一个“协程函数”,把你要异步进行的操作封装到一个函数中,而这个函数,还有一些特殊的语法如下
1> 返回值为:IEnumerator
2> 返回要写成:yield return(这个之后会详细说一下) - 第二步你需要详细“设计”你的协程函数,协程函数是可以自己控制其“中断”的,在协程执行到yield return返回时,这条协程就会被中断,而唤醒的时机就取决于你返回的东西了。
1> 返回0或null这类普通的数据类型东西将会在下一帧唤醒该协程。
2> 返回一个启动协程的方法调用,会在你启动的这个协程结束后再唤醒该协程。
3> 返回new WaitForSenconds(3.0f),这样可以控制在3s后再唤醒当前协程 - 第三步就是启动协程,使用StartCoroutine方法可以启动一个协程,参数就是协程函数的调用。
- 例子(因为大佬的例子真的很香我就照搬了,真的不是我懒[狗头])
public void Start()
{
StartCoroutine(CoroutineA(1, "协程启动"));
}
IEnumerator CoroutineA(int arg1, string arg2)
{
Debug.Log($"协程A被开启了");
yield return null;
Debug.Log("刚刚协程被暂停了一帧");
yield return new WaitForSeconds(1.0f);
Debug.Log("刚刚协程被暂停了一秒");
yield return StartCoroutine(CoroutineB(arg1, arg2));
Debug.Log("CoroutineB运行结束后协程A才被唤醒");
yield return new WaitForEndOfFrame();
Debug.Log("在这一帧的最后,协程被唤醒");
Debug.Log("协程A运行结束");
}
IEnumerator CoroutineB(int arg1, string arg2)
{
Debug.Log($"协程B被开启了,可以传参数,arg1={arg1}, arg2={arg2}");
yield return new WaitForSeconds(3.0f);
Debug.Log("协程B运行结束");
}
手动操作协程
- 之前说的东西是启动协程后就全程托管的东西,但在这里其实有其他方法可以手动操作协程。
- 首先协程的底层原理就是迭代器的控制,我们协程函数所返回的值就是一个迭代器,得到这个迭代器对象我们就可以通过这个迭代器手动控制这个协程的启动,获取返回值等操作。
- 调用 IEnumerator 的 MoveNext() 成员,会执行协程直到遇到第一个 yield return 或者执行完毕。
- 调用 IEnumerator 的 Current 成员,可以获得 yield return 后面接的返回值,该返回值可以是任何类型的对象。
需要注意
- 由于协程仍旧是跑在主线程上的缘故,切忌不要不加任何中断的搓上一个复杂算法进去,免得协程阻塞了给主线程干崩了。
- 如果你要做的操作并没有涉及UnityAPI,不如直接去开一个新的线程去完成你的耗时操作,完成后再唤醒主线程中的协程实现回调。