[Unity3D] 协程

目录

前言

学习来源:

一、什么是协程

二、协程的应用举例

三、协程的使用方式

3.1  启动

3.2  结束

3.3  嵌套

3.4  注意

四、Unity脚本的生命周期

五、yield速查表 


前言

学习笔记,仅供学习,不做商用,如有侵权,联系我删除即可

学习来源:

Unity使用手册

Unity 协程(Coroutine)原理与用法详解https://blog.csdn.net/xinzhilinger/article/details/116240688?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168189731016800217270387%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168189731016800217270387&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-116240688-null-null.142%5Ev84%5Econtrol_2,239%5Ev2%5Einsert_chatgpt&utm_term=unity%E5%8D%8F%E7%A8%8B&spm=1018.2226.3001.4187

 Unity-协程详解https://blog.csdn.net/qq_44705559/article/details/118052537

一、什么是协程

协程就像一个函数,能够暂停执行并将控制权返还给 Unity,然后在下一帧继续执行

协程本质上是一个用返回类型 IEnumerator 声明的函数,并在主体中的某个位置包含 yield return 语句。

yield 的所在行是暂停执行并随后在下一帧恢复的点

在 yield 语句之间可以正确保留任何变量或参数

默认情况下,协程将在执行 yield 后的帧上恢复,但也可以使用 WaitForSeconds 来引入时间延迟

注意:

协程不是多线程,它与主线程同时运行,它在主线程运行的同时开启另一段逻辑处理。
类似一个子线程单独出来处理一些问题,性能开销较小。
Unity的协程会在每帧结束之后去检测的条件是否满足,满足则执行yield return之后的代码。

二、协程的应用举例

以下来自  Unity Documentation手册 (V2020.1)  中的叙述:

游戏中的许多任务需要定期执行,最容易想到的方法是将任务包含在 Update 函数中。

但是,通常情况下,每秒将多次调用该函数。不需要以这样的频繁程度重复任务时,可以将其放在协程中来进行定期更新,而不是每一帧都更新。

这方面的一个示例可能是在附近有敌人时向玩家发出的警报。此代码可能如下所示:

function ProximityCheck() 
{
    for (int i = 0; i < enemies.Length; i++)
    {
        if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
                return true;
        }
    }
    
    return false;
}

如果有很多敌人,那么每帧都调用此函数可能会带来很大开销。但是,可以使用协程,每十分之一秒调用一次:

IEnumerator DoCheck() 
{
    for(;;) 
    {
        ProximityCheck();
        yield return new WaitForSeconds(.1f);
    }
}

这将大大减少所进行的检查次数,而不会对游戏运行过程产生任何明显影响。 

三、协程的使用方式

3.1  启动

要将协程设置为运行状态,必须使用返回类型为 IEnumerator 声明的 StartCoroutine 函数

  • StartCoroutine(string methodName):这种是没有参数的情况,直接通过方法名(字符串形式)来开启协程
  • StartCoroutine(IEnumerator routine):通过方法形式调用
  • StartCoroutine(string methodName,object values):带参数的通过方法名进行调用

3.2  结束

可以使用 StopCoroutine 和 StopAllCoroutines 来停止协程。 当用 SetActive(false) 禁用某个协程所附加到的游戏对象时,该协程也将停止。

调用 Destroy(example)(其中 example 是一个 MonoBehaviour 实例)会立即触发 OnDisable,并会处理协程,从而有效地停止协程。

最后,在帧的末尾调用 OnDestroy

通过在 MonoBehaviour 实例上将 enabled 设置为 false 来禁用 MonoBehaviour 时,协程不会停止。

  • StopCoroutine(string methodName)通过方法名(字符串)来进行
  • StopCoroutine(IEnumerator routine):通过方法形式来调用
  • StopCoroutine(Coroutine routine)通过指定的协程来关闭

注意:

如果我们是使用StartCoroutine(string methodName)来开启一个协程的

那么结束协程就只能使用StopCoroutine(string methodName)StopCoroutine(Coroutine routine)来结束协程

3.3  嵌套

利用yield return StartCoroution(其它协程);可以实现多个协程的嵌套使用。

3.4  注意

  • IEnumerator 类型的方法不能带 ref 或者 out 型的参数,但可以带被传递的引用
  • 在函数 Update 和 FixedUpdate 中不能使用 yield 语句,否则会报错, 但是可以启动协程
  • 在一个协程中,StartCoroutine()和 yield return StartCoroutine()是不一样的。
  • 前者仅仅是开始一个新的Coroutine,这个新的Coroutine和现有Coroutine并行执行。
  • 后者是返回一个新的Coroutine,是一个中断指令,当这个新的Coroutine执行完毕后,才继承执行现有Coroutine。

四、Unity脚本的生命周期

根据生命周期图,当程序中设置协程时,程序的执行顺序为:(假设当前帧为第1帧)

  1. 第1帧在start中开启协程,执行协程(自上而下),执行到yield return行后,将后面的内容挂起。
  2. 这时继续执行第1帧剩下的东西直到第1帧Update执行结束。
  3. 在每一帧的update与lateupdate之间对挂起的内容进行判断,判断是否满足return条件。
  • 若满足条件,则在第2帧的Update之后,在LateUpdate前,执行协程中yield return 以后的代码;
  • 若不满足条件,则继续执行第1帧的LateUpdate。

第2帧的处理方法与第1帧相同。

五、yield速查表 

yield语句 功能
yield return null; 下一帧再执行后续代码
yield return 0; 下一帧再执行后续代码
yield return 6;(任意数字) 下一帧再执行后续代码
yield break; 直接结束该协程的后续操作
yield return asyncOperation; 等异步操作结束后再执行后续代码
yield return StartCoroution(其它协程); 调用执行其它协程后再执行后续代码
yield return abc(); 等待abc操作完成后再执行后续代码
yield return new WaitForEndOfFrame(); 等待帧结束,等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前执行
yield return new WaitForSeconds(0.1f); 等待0.1秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间会受到Time.timeScale的影响);
yield return new WaitForSecondsRealtime(0.1f); 等待0.1秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间不受到Time.timeScale的影响);
yield return WaitForFixedUpdate(); 等待下一次FixedUpdate开始时再执行后续代码
yield return new WaitUntil() 将协同执行直到当输入的参数(或者委托)为true的时候
yield return new WaitWhile() 将协同执行直到 当输入的参数(或者委托)为false的时候

猜你喜欢

转载自blog.csdn.net/The___sky_/article/details/130250054