Unity核心原理(3)深入理解协程

协程的语法怎样理解?开发中怎样运用?这是Unity初学者都会面对的问题。

协程语法怎样理解:

1.协程,顾名思义,就是“协同程序”,用来实现协作。 2.比如在游戏中需要等待1秒后执行一个操作。我们不能让游戏主线程卡死等1秒,而是开启一个协程进行协作,协程同样是由主线程来驱动(所以说它不是线程),会在每一帧去检测它是否已经达到了完成的条件。比如条件是1秒后执行一个操作,那么在1秒后主线程对它检测时。条件满足,于是就执行先前设定好的相关操作。

为什么要有协程?

  1. Uniy核心逻辑是单线程,为了开发便利,统一生命周期管理,不需要考虑锁的问题。
  2. 一些导步操作非常耗时,比如资源加载,如果让用户去使用多线程开发,整个开发逻辑会非常复杂。而通过协程封装起来,方便用户使用。并且对于一些耗废时间的操作,Unity会在引擎底层通过多线程去完成,而协程则通过不断的访问这个操作的状态判断加载是否完成。

启动协程的方法:

  1. StartCoroutine(IEnumerator routine)
  2. StartCoroutine(string routine)或StartCoroutine(string routine,object value) 通过传入函数名字的字符串启动协程的性能开销要更高,但这种方式启动的协程可以通过StopCoroutine(string methondname)来终止,这种方式还有一个限制就是只能传递一个参数。

协程终止的方法

  1. StopCoroutine(string methondname)只能终止通过字符串名字启动的协程
  2. StopCoroutine(Coroutine coroutine)
  3. StopAllCoroutines()终止所有协程
  4. 在协程内部终止可以使用
yeild break;
  1. 还有一种方法是直接把物体的active属性设置为false,这里是一个大坑,容易引发bug
    (备注:以上都是针对当前这个MonoBehaviour中的协同程序而言)

协程的一些特性

  1. 在一个协程中可以启动另一个协程
  2. 一个协程可以暂停另一个协程
  3. 两个协程也可以同时并行工作
  4. 协程在执行过程中可以通过yield在任何时间点暂停,yeild返回的值决定了协程何时恢复执行
  5. 在多个游戏帧循环中进行操作时,协程表现十分出色,几乎没有额外性能开销
  6. StartCoroutine()函数总是会立即返回,不管你yeild返回的值是什么
  7. 多个协程结束时的顺序是无法保证与其启动顺序一致的,即使他们是在同一帧当中结束

关于yeild返回的值

  1. 可以是null,数字 ,字符串,布尔值甚至表达式,函数,嵌套协程。
  2. 当return是一个函数调用,赋值表达式,嵌套协程时,会直接调用这个函数或表达式。
  3. 协程一般情况下是在Update调用完成之后运行,在yeild后面的条件满足之前,协程会一直挂起在那里。
  4. 不同的yeild返回类型对应了不同的条件:
    1. null,数字,字符串:会在下一帧所有Update()函数运行之后继续运行
    2. WaitForSeconds:延迟指定的时间之后,在所有的Update()函数运行之后继续运行
    3. WaitForFixedUpdate:在所有FixedUpdate() 函数运行之后继续运行。(注意这里不是指下一帧,因为FixedUpdate()的帧率和Update()是不一样的)
    4. WWWW:当WWW资源加载成功以后继续运行。(其它的异步资源加载函数也是一样)
  1. StartCoroutine:运行完成嵌套的协程以后再继续运行。

如果还要继续深入研究协程的实现,可以查看《CLR via C#》以及《深入理解C#》这两本书中迭代器实现原理,Unity的底层就是通过它来实现的协程。

Unity里,一个典型的协程如下:

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    void Start() {
        StartCoroutine(FuncA());
    }

    IEnumerator FuncA() {
        Debug.Log("Log1");
        yield return new WaitForSeconds(1.0f);
        Debug.Log("Log2");
        yield return StartCoroutine(FuncB());
        Debug.Log("Log3");
    }

    IEnumerator FuncB() {
        Debug.Log("Log4");
        yield return new WaitForSeconds(2.0f);
        Debug.Log("Log5");
    }
}

运行输出结果为:

Log1
(等待1s)  
Log2  
Log4  
(等待2s)  
Log5  
Log3

注意:本内容来自:https://zhuanlan.zhihu.com/p/55420579 

猜你喜欢

转载自blog.csdn.net/xiaochenXIHUA/article/details/88426323
今日推荐