Unity协同使用初步总结(StartConroutine_IEnumerator & IEnumeratable)

来源:互联网 发布:应届生程序员面试题 编辑:程序博客网 时间:2024/06/05 06:22

关于协同有其他大牛发布的帖子比我写的更详细。传送门已备好=》http://blog.csdn.net/linuxheik/article/details/45392945

目的导向:当在Unity的日常开发工作中,一定有需要异步加载的地方,比如异步加载进程,异步加载内容。加载内容大都可以通过协同(StartContine)来实现,但是在使用协同的时候,有可能会因为不熟悉IEnumerator 与IEnumeratable两种属性的返回值(两者有一定的相同点与不同点),以及其对应的限制,清楚并明白这些内容 是这篇博客的内容。


协同返回类型  : IEnumerator与IEnumerable

IEnumerable :

可以实现基本的异步处理需求,但是这种返回值类型的协同方法中,是不能够访问操作对象的一些组件信息的。

IEnumerator :

同IEnumerable 一样,但是与IEnumerable 不用的是IEnumerator 可以访问到操作对象的组件信息,以及生成对象。

表现形式 :

返回类型IEnumerable的协同中,只能使用StartConrotine(string MethodName) 一种形式。

返回类型IEnumerator 的协同中,可以同时使用StartConrotine(string MethodName)&&StartConrotine(Method())两种类型

TIp 1: StartConrotine(string MethodName)的注册的协同可以通过StopConrotine(string MethodName)&&StopAllConrotine()来停止

Tip 2: StartConrotine( Method())的注册的协同通过StopAllConrotine()来停止

单线程:

在接下来的内容里 将提供一些内容来印证上述内容的正确性,也将补充单线程的内容。

这里的单线程是指在某一个时间里Unity只可能执行一条协程,并非是同时进行的。

1.当Unity线程在执行方法Start()中的协同方法的时候,会执行协同程序中Yield Return语句前的内容,遇到Yield Return 暂停该方法 返回继续往下执行Start()方法里的内容,以此类推,Start()方法可以推及除使用在Update等更新函数里的任一方法。

在协程Do中嵌套NewDo的协程,Unity时怎么操作的。

下面代码的输出顺序是

OutPut 1 => OutPut 2 =>OutPut 3 =>OutPut 4 =>OutPut 5 =>OutPut 6

class TestConrotine{private void Start(){Debug.Log ("OutPut 1");StartCoroutine (Do());Debug.Log ("OutPut 4");}IEnumerator Do(){Debug.Log ("OutPut 2");yield return StartCoroutine(NewDo ());Debug.Log ("OutPut 5");}IEnumerator NewDo(){Debug.Log ("OutPut 3");yield return new WaitForSeconds (2f);Debug.Log ("OutPut 6");}}


2.将Start里的协同的表现形式换成StartConrotine(string MethodName)的形式StartConrotine(Method())

其输出顺序 依然相同

OutPut 1 => OutPut 2 => OutPut 3 => OutPut 4 => OutPut 5 => OutPut 6

class TestConrotine{private void Start(){Debug.Log ("OutPut 1");StartCoroutine ("Do");Debug.Log ("OutPut 4");}IEnumerator Do(){Debug.Log ("OutPut 2");yield return StartCoroutine(NewDo ());Debug.Log ("OutPut 5");}IEnumerator NewDo(){Debug.Log ("OutPut 3");yield return new WaitForSeconds (2f);Debug.Log ("OutPut 6");}}

3.在协程Do和协程NewDo中加入获取组件的操作后得到的顺序是

其输出顺序

OutPut 1 => 

OutPut 2 => OutPut 2_1 ReCharge

=> OutPut 3 => OutPut 3_1ReCharge

=> OutPut 4

=> OutPut 5 => OutPut 5_1ReCharge

=> OutPut 6 => OutPut 6_1ReCharge


class TestConrotine:MonoBehaviour{private void Start(){Debug.Log ("OutPut 1");StartCoroutine ("Do");Debug.Log ("OutPut 4");}IEnumerator Do(){Debug.Log ("OutPut 2");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 2_1"+img_1.name);yield return StartCoroutine(NewDo ());Debug.Log ("OutPut 5");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 5_1"+img_1.name);}IEnumerator NewDo(){Debug.Log ("OutPut 3");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 3_1"+img_1.name);yield return new WaitForSeconds (2f);Debug.Log ("OutPut 6");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 6_1"+img_2.name);}}

4.将Do的返回值类型由IEnumerator改为IEnumeratable之后

其打印的顺序为

OutPut 1 => OutPut 4 

class TestConrotine:MonoBehaviour{private void Start(){Debug.Log ("OutPut 1");StartCoroutine ("Do");Debug.Log ("OutPut 4");}IEnumerable Do(){Debug.Log ("OutPut 2");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 2_1"+img_1.name);yield return StartCoroutine(NewDo ());Debug.Log ("OutPut 5");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 5_1"+img_1.name);}IEnumerator NewDo(){Debug.Log ("OutPut 3");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 3_1"+img_1.name);yield return new WaitForSeconds (2f);Debug.Log ("OutPut 6");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 6_1"+img_2.name);}}

5.将Do的返回值类型不变将NewDo的返回值类型改为IEnumerator

其打印的顺序为

OutPut 1 =>

=> OutPut 2 => OutPut 2_1ReCharge

=> OutPut 4 

=> OutPut 5=> OutPut 5_1ReCharge


class TestConrotine:MonoBehaviour{private void Start(){Debug.Log ("OutPut 1");StartCoroutine ("Do");Debug.Log ("OutPut 4");}IEnumerator Do(){Debug.Log ("OutPut 2");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 2_1"+img_1.name);yield return StartCoroutine("NewDo");Debug.Log ("OutPut 5");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 5_1"+img_1.name);}IEnumerable NewDo(){Debug.Log ("OutPut 3");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 3_1"+img_1.name);yield return new WaitForSeconds (2f);Debug.Log ("OutPut 6");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 6_1"+img_2.name);}}

6.将两者的返回值都置为IEnumerator ,若是在StartCoroutine ("Do")后加上StopConrotine("Do")会怎么样呢?

来看下他们的输出顺序

可以看得出只有5的部分没有打印出来

OutPut 1 => 

OutPut 2 => OutPut 2_1 ReCharge

=> OutPut 3 => OutPut 3_1ReCharge

=> OutPut 4

=> OutPut 6 => OutPut 6_1 ReCharge

class TestConrotine:MonoBehaviour{private void Start(){Debug.Log ("OutPut 1");StartCoroutine ("Do");StopCoroutine ("Do");Debug.Log ("OutPut 4");}IEnumerator Do(){Debug.Log ("OutPut 2");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 2_1"+img_1.name);yield return StartCoroutine("NewDo");Debug.Log ("OutPut 5");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 5_1"+img_1.name);}IEnumerator NewDo(){Debug.Log ("OutPut 3");Image img_1= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 3_1"+img_1.name);yield return new WaitForSeconds (2f);Debug.Log ("OutPut 6");Image img_2= transform.Find("ReCharge").GetComponent<Image>();Debug.Log ("OutPut 6_1"+img_2.name);}}

由此可见

  1.协同程序的实例化并不具备传递性(A=>B=>C,操作A即可影响到C,暂且将其定义为传递性)

  2.unity主线程运行时会优先运行Yield 语句前的代码,并非是将当前代码运行完毕之后再来开始执行代码。

  3.并非有些资料里说的那样,协同不能获取Unity组件信息,但也不能完全否认,毕竟技术革新的周期是很快的。





原创粉丝点击