StartCoroutine的学习记录

StartCoroutine的使用:

IEnumerator  Wait(float waitTimeValue){

//things before wait

yield return new WaitForSeconds(waitTimeValue);

//thigs after wait;

}

SatrtCoroutine(Wait(5.0f));

刚接触StartCoroutine时,只知道可以通过这种方式进行延时操作,至于IEnumerator类型,yield return这种奇怪的语句以及

调用的时候要在StartCoroutine()里进行这几个问题,一直是一脸蒙蔽,什么鬼嘛这是,

在慢慢看了一些博主的文章后,对这几个问题有了初步的认识,就在这里记录下来:


1.IEnumerator

IEnumerator和yield return会构造出一个迭代器,迭代器几乎经常在用,例如:

int[] array=new int[]{1,2,3};

foreach(int i in array){

print(i);

}

数组的遍历过程实际上就是一个迭代器应用过程,只不过这个迭代器是由编译器帮我们实现,在编译器的内部,上面的代码类似这个样子(真正的比下面的要复杂):

int[] array=new int[]{1,2,3};

IEnumerator e=array.GetEnumerator();

while(e.MoveNext()){

print(Current);

}

至于迭代器内的方法MoveNext()和属性Current是IEnumerator这个接口定义的,这里是IEnumerator的完整声明:

public interface IEnumerator
    {
        //
        // 摘要:
        //     获取集合中的当前元素。
        //
        // 返回结果:
        //     集合中的当前元素。
        //
        // 异常:
        //   T:System.InvalidOperationException:
        //     枚举数定位在该集合的第一个元素之前或最后一个元素之后。
        object Current { get; }


        //
        // 摘要:
        //     将枚举数推进到集合的下一个元素。
        //
        // 返回结果:
        //     如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。
        //
        // 异常:
        //   T:System.InvalidOperationException:
        //     在创建了枚举数后集合被修改了。
        bool MoveNext();
        //
        // 摘要:
        //     将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
        //
        // 异常:
        //   T:System.InvalidOperationException:
        //     在创建了枚举数后集合被修改了。
        void Reset();
    }


2.yield return是干什么的

yield return 是C#2.0以后引入的现实迭代器的一种简便语法,在之前如果要实现一个完整的迭代器
需要实现IEnumerable和IEnumerator这两个接口,而使用yield retrun可以省略这两个步骤:
例如:
IEnumerator Test(){
yield return 1;
yield retutn 2;
yield retrun 3;
}
编译器会生成类似代码:
public class InnerEnumerable:IEnumerable{
public class InnerEnumerator:IEnumerator{
int[] array=new int[]{1,2,3};
int currentIndex=-1

public bool MoveNext(){
++currentIndex;
return current}

public Object Current{
get{return array[currentIndex];}
}


public void Reset(){
throw new Exception("error");
}
}
public IEnumerator GetEnumerator(){
return new InnerEnumerator();
}
}


IEnumerator Test(){
InnerEnumerable e= new InnerEnumerable();
return e.GetEnumerator();

这里可以将IEnumerable看成是IEnumerator的工厂模式,通过yield return让编译器实现IEnumerable和IEnumerator这两个接口


3.为什么调用的时候要被StartCoroutine()调用

这里就和实现延时过程有关系了,WaitForSeconds,WaitForEndFrame等类中并没有进行延时的处理,而他们的父类,yieldInstruction中

也并没有进行延时的处理,因为真正的延时处理是在StartCoroutine中进行的,StartCoroutine()传入的参数是IEnumerator,

StartCoroutine会对IEnumerator的MoveNext()进行调用,但是,如果这个IEnumerator是WaitForSeconds,WaitFaorEndFrame等类型

StartCoroutine就会特殊对待,执行完延时等待后,再调用MoveNext();

http://blog.csdn.net/tkokof1/article/details/11842673 这篇博主实现了自己的WaitForSeconds的功能,写的非常详细,以上内容也是基于此文进行的整理


4.StartCoroutine的嵌套执行顺序

void Start () {
        Debug.Log("start1");
        StartCoroutine(Test());
        Debug.Log("start2");
    }

    IEnumerator Test()
    {
        Debug.Log("test1");
        yield return StartCoroutine(DoSomething());
        Debug.Log("test2");
    }

    IEnumerator DoSomething()
    {
        Debug.Log("do something 1");
        yield return null;
        Debug.Log("do something 2");
    }
输出结果:

start1

test1

do something 1

start2

do something 2

test2

StartCoroutine中嵌套一个yield return StartCoroutine,第一个StartCoroutine会等到第二个StartCoroutine中所有代码结束后再继续执行,而第二个StartCoroutine中的yield语句会先返回第一个,然后立即返回他的调用处,也就是调用处会继续执行,而第一个StartCoroutine会等待第二个执行完再继续执行。

你可能感兴趣的:(学习笔记,Unity)