迭代器
迭代器: 用于遍历可迭代集合的工具,下一个元素的引用由上一个迭代而来。
如果对象需要能被 foreach 迭代遍历或对外提供迭代器用于遍历,则需实现 IEnumerable 接口。
传统写法:
using System;
using System.Collections.Generic;
using System.Collections;
class A : IEnumerable
{
List<int> list;
//对外提供迭代该类对象的迭代器
public IEnumerator GetEnumerator()
{
//直接返回需要被迭代遍历的对象的迭代器或自定义迭代器
//return list.GetEnumerator();
return new AEnumerator() { list = this.list};
}
}
class AEnumerator : IEnumerator
{
public object Current { get => list[index]; }
public List<int> list;
public int index = -1;
public bool MoveNext()
{
index++;
return index < list.Count;
}
public void Reset()
{
index = -1;
}
}
使用
A a = new A();
IEnumerator iterator = a.GetEnumerator();
while (iterator.MoveNext())
{
Console.WriteLine(iterator.Current);
}
//或者使用foreach
foreach(var item in a){
Console.WriteLine(item);
}
yield return写法:
class A : IEnumerable
{
List<int> list;
public IEnumerator GetEnumerator()
{
for(int i = 0; i < list.Count; ++i)
{
yield return list[i];
}
}
}
这样写代码简洁了不少,但外部的迭代调用方式是不变的。
yield return的原理: 每次调用 MoveNext(),都会执行一段代码,直到遇到 yield return 退出,yield return 的结果作为 Current 的值。下一次调用 MoveNext(),从上一次 yield return 的地方继续往下执行。
协程
中断: yield break;
yield return
-- WaitForFixedUpdate //在FixedUpdate后执行
-- null、0、...//在每帧Update之后执行
--WaitForEndOfFrame //在每帧结束后执行
--WWW //在请求结束后执行
--WaitForSeconds //在几秒后再调用
Start也可写作协程
会被 Unity 在 Start 时自动调用,按照普通协程执行。
private IEnumerator Start(){
yield return xxx;
}
协程的开启
1.StartCoroutine(Fun(arg));
优点:
性能开销小,支持多参数调用;
缺点:
无法单独停止该协程
StopCoroutine(Fun(arg)) 是无法停止该类协程的
2.StartCoroutine(string methodName, object value = null);
缺点:最多一个参数,且性能开销大
嵌套协程
private IEnumerator Fun1(){
yield return StartCoroutine(Fun2());
print("xx"); //会等到fun2协程执行完毕
}
private IEnumerator Fun2(){
yield return new WaitForSeconds(2);
}
协程的停止
StopCoroutine(string):只能停止以字符串为参开启的协程
StopAllCoroutine():停止开启的所有协程
协程应用
将耗时操作写在随时间进行的协程中处理
将需分步处理的内容通过一次 StartCoroutine 处理
注意事项
- 可以定义静态协程
- IEnumerator类型的方法不能带ref或者out型的参数
- 协程是依赖 GameObject 的,而不是脚本,所以协程开启后禁用脚本并不能停止协程,禁用 gameObject 才能