您的位置:首页 > 移动开发 > Unity3D

关于C# IEnumerator、yield、Unity3D协程的一些东西

2015-10-22 13:18 676 查看
在学习Unity3D的协程,其中需要C#中IEnumerator的使用,主要在看http://www.cnblogs.com/neverdie/p/3792766.html这篇文章。

对其中一些地方一开始没太看懂,看懂以后总结在这里。

(出处 http://www.cnblogs.com/neverdie/ ,By 王选易)

IEnumerator TellMeASecret(){
PlayAnimation("LeanInConspiratorially");
while(playingAnimation)
yield return null;

Say("I stole the cookie from the cookie jar!");
while(speaking)
yield return null;

PlayAnimation("LeanOutRelieved");
while(playingAnimation)
yield return null;
}(出处 http://www.cnblogs.com/neverdie/ ,By 王选易)


关于这一段一开始不太懂,不明白第一个yield前面为什么要加while(后面两个同理),后来想明白了,是在PlayAnimation这个播放动画函数所播放的动画结束前,playingAnimation这个bool一直为true,这样写可以避免播放动画过程中调用TellMeASecret的MoveNext后开始执行Say函数的结果,这个结果是不应该发生的。

自己总结一下,IEnumerator的使用,就像是一个函数内部可以通过for循环if判断等逻辑语句甚至是与函数外部变量共同动态维护顺序执行队列,在函数外部通过MoveNext来依次执行队列中的语句。

Unity3D中yield的几种基本用法:(出处 http://www.cnblogs.com/neverdie/ ,By 王选易)

Normal coroutine updates are run after the Update function returns. A coroutine is a function that can suspend its execution (yield) until the given YieldInstruction finishes. Different uses of Coroutines:

yield; The coroutine will continue after all Update functions have been called on the next frame.
yield WaitForSeconds(2); Continue after a specified time delay, after all Update functions have been called for the frame
yield WaitForFixedUpdate(); Continue after all FixedUpdate has been called on all scripts
yield WWW Continue after a WWW download has completed.
yield StartCoroutine(MyFunc); Chains the coroutine, and will wait for the MyFunc coroutine to complete first.


yield的几种灵活用法:(出处 http://www.cnblogs.com/neverdie/ ,By 王选易)

YieldInstruction y;

if(something)
y = null;else if(somethingElse)
y = new WaitForEndOfFrame();else
y = new WaitForSeconds(1.0f);

yield return y;


第二个,由于一个协程只是一个迭代器块而已,所以你也可以自己遍历它,这在一些场景下很有用,例如在对协程是否执行加上条件判断的时候:

IEnumerator DoSomething(){
/* ... */}

IEnumerator DoSomethingUnlessInterrupted(){
IEnumerator e = DoSomething();
bool interrupted = false;
while(!interrupted)
{
e.MoveNext();
yield return e.Current;
interrupted = HasBeenInterrupted();
}}


第三个,由于协程可以yield协程,所以我们可以自己创建一个协程函数,如下:

IEnumerator UntilTrueCoroutine(Func fn){
while(!fn()) yield return null;}

Coroutine UntilTrue(Func fn){
return StartCoroutine(UntilTrueCoroutine(fn));}

IEnumerator SomeTask(){
/* ... */
yield return UntilTrue(() => _lives < 3);
/* ... */}


关于yield的WaitsForSeconds()的用法

private IEnumerator DelayExcute(float delayTime = 0.5f)
{

//statement1

yield return new WaitForSeconds(delayTime);

//statement2

}

public void UnLightHightGameObjs(float duration = 0.5f)//遮罩层消失
{

PlayAnim();//先播放动画

StartCoroutine(DelayExcute());//延迟执行 //方法一

IEnumeratore = DelayExcute();
//方法二(包括while)

while(e.MoveNext)

{

//statement

}

}

项目里有一个半秒的动画,动画完毕需要执行一个函数DelayExcute(),一开始使用的是方法二的用法,以为能在半秒后才执行DelayExcute(),结果效果还是直接执行了。

搜了一下采用了方法一,成功了。

想了一下,猜测MoveNext()就是强行把指针移到下一个yield的地方,并且执行与上一个yield之间的函数,而StartCoroutine()则是解析到WaitForSeconds()函数后设定了一个半秒后执行的延迟。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: