协程
介绍
- 不是进程或线程,执行过程类似于子例程或者说不带返回值的函数调用。
- 达到类似多线程的并发执行效果
- 在yield return 处移交控制权。
- 可以提前结束执行
使用
- 声明方式
- IEnumerator [methodName] (){yield return XXX }
- IEnumerator [methodName] (){yield return T }
开启方式
- public Coroutine StartCoroutine(IEnumerator methodName());
- public Coroutine StartCoroutine(string methodName);
- public Coroutine StartCoroutine(string methodName, [DefaultValue(“null”)] object value);
StartCoroutine会立即执行开启传入的协程并返回一个Coroutine类型。
结束方式
- public void StopCoroutine(IEnumerator methodName());
- public void StopCoroutine(string methodName);
public void StopCoroutine(Coroutine routine);
前两种结束方式根据参数类型分别对应开启方式的三种,第三种结束方式传入参数为StartCoroutine所返回的Coroutine类型实例。
内部结束执行
yield break;
执行顺序:开启协程后会立即开始执行协程中的命令,直到遇到第一个yield return 时会暂时把控制权移交出去并继续执行其它代码,此时这个协程在这一帧中已经无法继续往下执行了,下一帧开始后根据生命周期函数的执行顺序去访问一次协程,如果可以则会从上次yield return的地方继续往下执行,以此类推。
关于协程中各类yield return在一帧中执行的顺序可以查阅Unity目录下的Editor/Data/Documentation/en/Manual/ExecutionOrder.html的生命周期图,也可通过Unity内帮助进行访问。
协程本质
协程的本质是迭代器,它们被封装在IEnumerator,IEnumerable以及他们俩的泛型形式IEnumerator,IEnumerable之中。其中IEnumerator还实现了IDisposable接口。
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
public interface IEnumerator : IEnumerator, IDisposable
{
T Current { get; }
}
public interface IEnumerable : IEnumerable
{
IEnumerator GetEnumerator();
}
public interface IDisposable
{
void Dispose();
}IEnumerable 用来获取一个迭代器(IEnumerator),而迭代工作实际在IEnumerator中实现,这一过程可以通过代码来模拟完成。
- 执行一个协程IEnumerator,将返回得到一个新类型实例 ,循环执行该实例的MoveNext方法,如果MoveNext返回true则打印出该实例的属性Current,这样可以看到在协程中yield return的值都被依次打印出来,这就是foreach方法所执行的大概过程。
- IEnumerable提供了一个GetEnumerator的方法用来获取迭代器。
3.协程中所返回的值被迭代器保存在堆上以便后面继续使用,每次调用MoveNext()方法时会从上次yield return的地方继续。 - 其实迭代器这种设计在多种主流语言中都可见到,如Java,ECMAScript,Python等,通常多使用于集合类数据结构的遍历。
迭代器是什么
- 迭代器工作原理是使用状态机,在迭代器创建完一个新类型且一次未调用MoveNext前,状态机的状态为0(初始状态),
- 此后在迭代器每次状态改变前的状态都会被重置为-1(预备状态/结束状态),
- 然后执行过程中的代码并记录当前返回值,在一系列状态完成之后状态会依次变为1,2,3,4…(完成状态)以便记录所执行到的位置。
- 另外,由于IEnumerable还需额外执行GetEnumerator方法来获取到IEnumerator,状态机用-2(转接状态)来标记这一阶段的状态
参考资料:
- 《使用C#语言开发跨平台游戏》—陈嘉栋
- Unity官方文档
本文介绍了Unity中的协程Coroutine,它不是进程或线程,而是通过yield return实现类似多线程并发执行的效果。协程可以被声明为IEnumerator类型的方法,并通过StartCoroutine开启,通过StopCoroutine结束。协程本质是迭代器,实现于IEnumerator和IEnumerable接口。文章详细阐述了协程的执行顺序、生命周期以及与其他语言中迭代器的相似性。
1110





