IEnumerator 协程 全称协同程序
每次 执行协程 时,都会新建一个新(伪)线程去执行,第二次执行不会影响上一次的执行,
结论是:协程适用于同一时间只运行一份函数的情况,如果同一时间运行多份同一个协程就会难以管理
void Start()
{
for (int i = 0; i < 7; i++)
{
StartCoroutine(SampleFunc(7)); //第二次执行时,会重新开启伪新线程执行,不会影响打断第一次执行,这里会开启7个伪线程,每个线程单独执行SampleFunc()函数
}
}
IEnumerator SampleFunc(int a)
{
while (a != 0)
{
a--;
Debug.Log("a=============== "+ a); //输出了 7*7=49 句 a 的值
yield return new WaitForSeconds(0.1f);
}
}
表达式
yield return null; //等1帧执行.暂停协同程序,下一帧再继续往下执行. 通知协程管理器,我到这个点要中断一下,下一帧从这个地方运行而已.
yield return 0; //同yield return null;,数字改多大没用,都是等一帧
yield return 666; //同yield return null;,数字改多大没用,都是等一帧
yield break; //不在执行下面的语句,直接rerun
yield return asynaOperation; //等待异步操作执行完毕后执行
yield return StartCoroutine(coroutine); //等待子协程执行完毕后再执行
yield return WWW(); 在WWW下载完成之后……waits for a web request to complete (resumes as if WaitForSeconds or null)
yield return new WaitForEndOfFrame(); //等待帧结束,等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前。用在while循环里减少死机
yield return new WaitForSeconds(0.3f);//等待0.3秒 , 一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后注意:受Time.timeScale影响,当Time.timeScale = 0f 时,yield return new WaitForSecond(x) 将不会满足。
yield return new WaitForFixedUpdate(); // 所有脚本上的FixedUpdate函数已经执行调用之后持续
yield return new WaitUntil:将协同执行直到 当输入的参数(或者委托)为true的时候…… || yield return new WaitUntil(() => frame >= 10);
yield return new WaitWhile:将协同执行直到 当输入的参数(或者委托)为false的时候…… || yield return new WaitWhile(() => frame < 10);
协程其实就是一个IEnumerator(迭代器),IEnumerator 接口有两个方法 Current 和 MoveNext() ,只有当MoveNext()返回 true时才可以访问 Current,否则会报错。迭代器方法运行到 yield return 语句时,会返回一个expression表达式并保留当前在代码中的位置。 当下次调用迭代器函数时执行从该位置重新启动。
Unity在每帧做的工作就是:调用 协程(迭代器)MoveNext() 方法,如果返回 true ,就从当前位置继续往下执行。
yield return 被会“翻译”为一个 IEnmerator 对象,这个对象实现的 MoveNext() 包含函数内所有 yield return 的处理
函数内有多少个 yield return 在对应的 MoveNext() 就会返回多少次 true (不包含嵌套)。
另外非常重要的一点的是:同一个函数内的其他代码(不是 yield return 语句)会被移到 MoveNext 中去,也就是说,每次 MoveNext 都会顺带执行同一个函数中 yield return 之前,之后 和两个 yield return 之间的代码。
协程不是线程,也不是异步执行的,是Unity每帧LateUpdate()之后都会去处理的函数
协程执行流程
1 如果 [gameObject激活] 并且 [脚本.enable=true ] 状态 下, StartCoroutine启动了协程 ,协程会立即运行到第一个 yield return 语句处,控制权交给外部
2. 等待Unity在下一帧(Frame)LateUpdate()之后
3.检查协程是否允许的条件 :脚本.enabled = false 协程会照常运行
a.检测 gameObject 是否处于激活(active) ,不激活不运行
b.检测 yield return 后面的表达式,如果满足就继续向下执行
IEnumerator 协程 全称协同程序
1.必须在MonoBehaviour或继承于MonoBehaviour的类中调用 yield coroutine。
2.StartCoroutine所在脚本物体必须是激活的.才能执行不报错.
MonoBehaviour.StartCoroutine方法即可开启一个协同程序,
StopCoroutine(methodName())//来终止一个协同程序,
StopAllCoroutines()//来终止所有可以终止的协同程序,
MonoBehaviour.enabled = false 协程会照常运行,gameObject.SetActive(false) 停止,即使在Inspector把 gameObject 激活还是没有继续执行
//yield return 被会“翻译”为一个 IEnmerator 对象
//yiled return 本质上和return作用一样,将当前函数返回。只不过下一次再调用这个函数,可以从yiled return的下一句开始执行,函数本身的变量也都会一直保存上一次调用的状态。
//yield return的作用是在执行到这行代码之后,将控制权立即交还给外部。yield return之后的代码会在外部代码再次调用MoveNext时才会执行,直到下一个yield return——或是迭代结束
yield return expression; //只有表达式完全执行结束才会继续执行后面的代码
结束返回:
在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它的形式为下列之一⑥:
yield return <expression_r>;
yield break;
//==========================列0=============================
void Start()
{
StartCoroutine(WaitEnd (5f)); // 瞬间执行 WaitEnd函数 ,和下面的函数
StartCoroutine (WaitFrameEnd());// 瞬间执行 WaitFrameEnd函数 ,和下面的函数
StartCoroutine (WaitFixedUpdate());// 瞬间执行 WaitFixedUpdate函数 ,和下面的函数
}
IEnumerator WaitEnd(float time)
{ // 执行同时,其他函数也再并行
yield return new WaitForSeconds(time);
// 5秒后到这里 ,执行这里的
Debug.Log ("WaitForSeconds:"+time);
}
IEnumerator WaitFrameEnd()
{
yield return new WaitForEndOfFrame();
// 等待当前帧结束
Debug.Log ("WaitForEndOfFrame:"+Time.time);
}
IEnumerator WaitFixedUpdate()
{
yield return new WaitForFixedUpdate();
// 等待每次 Update 执行一次后调用
Debug.Log ("WaitForFixedUpdate:"+Time.time);
}
//==========================列1=============================
IEnumerator WaitAndshen()
{
yield return new WaitForSeconds(0.3f);
//上面的时间到了才能执行下面的.
}
//注意 StartCoroutine 所在脚本物体必须是激活的.才能执行不报错.
StartCoroutine( WaitAndshen());
//==========================列2 带参数的协程=============================
void Start()
{
StartCoroutine(_PlayLoopSound(clip, delay, time, fadeInTime, fadeOutTime));
}
IEnumerator _PlayLoopSound(AudioClip clip, float delay, float time, float fadeInTime, float fadeOutTime)
{
}