当前位置:   article > 正文

Unity协同详解以及与多线程的区别使用_协调 unity

协调 unity

转载自:http://blog.csdn.net/linuxheik/article/details/45392945

1.什么是协调程序

        unity协程是一个能暂停执行,暂停后立即返回,直到中断指令完成后继续执行的函数。
        它类似一个子线程单独出来处理一些问题,性能开销较小,但是他在一个MonoBehaviour提供的主线程里只能有一个处于运行状态的协程。
2.协同程序的特点
1、协程在中断指令(YieldInstruction)产生时暂停执行
2、协程一暂停执行便立即返回 //中断协程后返回主函数,暂停结束后继续执行协程剩余的函数。
3、中断指令完成后从中断指令的下一行继续执行
        4、同一时刻、一个脚本实例中可以有多个暂停的协程,但只有一个运行着的协程
        5、函数体全部执行完后,协程结束
        6、协程可以很好的控制跨越一定帧数后执行的行为
        7、协程在性能上、相比于一般函数几乎没有更多的开销


3.创建一个协程函数
   IEnumerator methodName(Object parameter1,Object parameter2,...){
// to do something
yield return YieldInstruction/other/null;
// to do something else
}
    注意:
    协同函数的返回值的类型必须是Coroutine,Coroutine继承与Yieldinstruction。
    所以协同程序的返回类型就只能是null,等待的时间,等待的帧数。。由此可见WWW 也是实现了Coroutine的~
4.开始一个协同程序
通过MonoBehaviour提供的StartCoroutine方法来实现启动协同程序。
1、StartCoroutine(IEnumerator routine);
优点:灵活,性能开销小。
缺点:无法单独的停止这个协程,如果需要停止这个协程只能等待协同程序运行完毕或则使用StopAllCoroutine();方法。
2、StartCoroutine (methodName:string, value : object = null);
优点:可以直接通过传入协同程序的方法名来停止这个协程:StopCoroutine(string methodName);
缺点:性能的开销较大,只能传递一个参数。

5.停止协同程序
1、StopCoroutine(string methodName);
2、StopAllCoroutine();
3、设置gameobject的active为false时可以终止协同程序,但是再次设置为true后协程不会再启动。


6.协同程序的执行顺序
开始协同程序 -> 执行协同程序 -> 中断协同程序(中断指令)-> 返回上层继续执行
->中断指令结束后继续执行协同程序剩下的内容
7.协同程序的注意事项
 1、不能再Update或者FixUpdate方法中使用协同程序,否则会报错。
 2、关于中断指令:
中断指令/YieldInstruction,一个协程收到中断指令后暂停执行,返回上层执行同时等待这个指令达成后继续执行。
        
 指令                      描述                          实现


WaitForSeconds          等待指定秒数            yield return new WaitForSeconds(2);          
WaitForFixedUpdate      等待一个固定帧          yield return new WaitForFixedUpdate();   
WaitForEndOfFrame       等待帧结束              yield return new WaitForEndOfFrame();                         
StartCoroutine          等待一个新协程暂停      yield return StartCoroutine(other coroutine);   
WWW                     等待一个加载完成        yield return www;
注意:
1、一个协程A里在中断指令里再启动一个协程B,在yield return StartCoroutine时执行的顺序是:
①:先执行新协程B;
②:新协程B暂停后向上返回协程A,A协程暂停,返回协程A的上层函数;
③:因为决定协程A是否结束的标志是新协程B是否结束,所以当新协程B结束后返回协程A继续执行余下的内容;
④:协程A执行结束。
        2、关于WWW的中断指令可参考API:
You can inspect the isDone property to see if the download has completed or yield the download object to automatically wait until it is (without blocking the rest of the game). 
你可以检查isDone属性来查看是否已经下载完成,或者yield自动等待下载物体,
直到它被下载完成(不会影响游戏的其余部分)。


 3、协同程序的中断返回机制也可用于指定时间间隔执行一个程序:
//每3秒执行一次
while(true){
//to do something
yield return new WaitForSeconds(3);
}
             
8.例子
lg1、举例说明协同程序的执行流程
using UnityEngine;
using System.Collections;


public class SimpleCoroutine : MonoBehaviour {
/// <summary>
/// Start, 协程的执行流程
/// Start函数运行,输出“1”,然后开始协程Do;
/// Do输出“2”,然后开始协程newDo;
/// newDo输出“3”,产生中断指令后暂停,立即返回Do;
/// Do产生中断指令后暂停,Do暂停并立即返回Start函数;
/// Start执行StartCoroutine的下一条语句:输出“4”;
/// 2秒后,newDo的中断指令完成并继续执行,输出“5”,协程newDo结束;
/// Do的中断指令因为协程newDo的结束而完成并继续执行,输出“6”,协程Do结束。
/// </summary>
void Start () {
Debug.Log("1");
StartCoroutine(Do());
Debug.Log("4");
}
IEnumerator Do() {
Debug.Log("2");
yield return StartCoroutine(newDo());//WaitForSeconds(5);
Debug.Log("6");
}
IEnumerator newDo() {
Debug.Log("3");
yield return new WaitForSeconds(2);
Debug.Log("5");
}
}
//输出结果顺序是,1,2,3,4,5,6


lg2、加载指令(通过WWW加载本地文件)
private string path = "file://F:/Resource/Dragon.unity3d";
void OnGUI(){
if(GUI.Button(new Rect(200,200,150,30),"点击进入协同程序")){
Debug.Log("1");
StartCoroutine(loadLocalBundle(path));
Debug.Log("3");
}
}
private IEnumerator loadLocalBundle(string url){
Debug.Log("2");
using(WWW www = new WWW(url)){
yield return www;
Debug.Log("4");
if(www.error != null){
var bytes = www.bytes;
}
AssetBundle ab = www.assetBundle;
GameObject gameObject = ab.mainAsset as GameObject;
Instantiate(gameObject);
Debug.Log("5");
Debug.Log("load local assetBundle finished..."+gameObject);
}
}
注意:
//大概执行流程,点击按钮后开始执行协同程序,WWW按照提供的url进行加载,完毕后 yield return www;中断指令跳转到主线程。
//主线程继续执行其他内容,www在加载完成后跳出中断继续执行余下内容。

//加载完毕,实例化加载内容。




1、 协程 不是 线程, 协同程序是 不同步 的 一个线程在程序中和其他线程是异步运行的,在多处理器机器中一个线程可以同时与所有其他线程的实时运行其代码,这使得线程编程能够解

1.协程 不是 线程,协同程序是 不同步 

      一个线程在程序中和其他线程是异步运行的,在多处理器机器中一个线程可以同时与所有其他线程的实时运行其代码,这使得线程编程能够解决很复杂的事情,因为可能在相同的时间里一个线程在改变它而另一个线程正在读取它,这意味着另一个线程实际上可以改变的东西在游戏中处理的中间似乎是你的源代码一行。这是因为你写的代码是由机器变成汇编语言,更是更复杂。正因为如此,你必须通过锁,以确保这种情况不会由任何确保没有共享内存发生。或者通过锁定其他线程使用同一块内存,当他们在读取或更改时。

2、什么是协程?

      协同程序绝对不是一个线程。这意味着在同一时间只有一个协同程序在执行,它会被执行在游戏的主线程上,所以实际上在同一时间游戏的核心只有一个协同程序在运行[这段翻译的不太好]

     你永远不需要担心同步或锁定一个值当你正在编写一个协同程序。你有完全的控制权,直到你的代码执行到 yiedld

  因此总结一下协程的定义

    协程只是部分执行,并假定在适当的条件得到满足,在未来的某一时刻将被恢复,直到它的工作完成

Unity processes coroutines every frame of the game for every object that has one or more running.  The processing occurs after Update and before LateUpdate for most yield statements, but there are special cases:

Unity的流程协同程序在游戏的每一帧每个对象为具有一个或多个正在运行的。Update() 之后,LateUpdate()之前 ,发生的 yield 语句的处理



Unity,WWW加载,本地储存,协同程序,Coroutine2014-02-28

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/126732
推荐阅读
相关标签
  

闽ICP备14008679号