【转】关于Unity协同程序(Coroutine)的全面解析
http://www.unity.5helpyou.com/2658.html
本篇文章我们学习下unity3d中协程Coroutine的的原理及使用
1.什么是协调程序
unity协程是一个能暂停执行,暂停后立即返回,直到中断指令完成后继续执行的函数。
它类似一个子线程单独出来处理一些问题,性能开销较小,但是他在一个MonoBehaviour提供的主线程里只能有一个处于运行状态的协程。
2.协同程序的特点
1、协程在中断指令(YieldInstruction)产生时暂停执行
2、协程一暂停执行便立即返回 //中断协程后返回主函数,暂停结束后继续执行协程剩余的函数。
3、中断指令完成后从中断指令的下一行继续执行
4、同一时刻、一个脚本实例中可以有多个暂停的协程,但只有一个运行着的协程
5、函数体全部执行完后,协程结束
6、协程可以很好的控制跨越一定帧数后执行的行为
7、协程在性能上、相比于一般函数几乎没有更多的开销
3.创建一个协程函数
1
2
3
4
5
6
|
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、协同程序的中断返回机制也可用于指定时间间隔执行一个程序:
1
2
3
4
5
|
//每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
[/csharp]
lg2、加载指令(通过WWW加载本地文件)
1
|
|
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在加载完成后跳出中断继续执行余下内容。
加载完毕,实例化加载内容。
【转】关于Unity协同程序(Coroutine)的全面解析的更多相关文章
- Lua 协同程序(coroutine)
什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西. 协同是非常 ...
- Lua中的协同程序 coroutine
Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...
- Lua中的协同程序 coroutine(转)
Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...
- Lua 学习之基础篇九<Lua 协同程序(Coroutine)>
引言 讲到协程,首先来介绍一下线程和协程的区别 lua协程和多线程 相同之处:拥有自己独立的桟.局部变量和PC计数器,同时又与其他协程共享全局变量和其他大部分东西 不同之处:一个多线程程序可以同时运行 ...
- Unity 协同程序
定义协同程序: IEnumerator test() { Debug.log("test 1"); yeild return WaitForSecond(3.0f); Debug. ...
- 【转】Unity中的协同程序-使用Promise进行封装(一)
原文:http://gad.qq.com/program/translateview/7170767 译者:陈敬凤(nunu) 审校:王磊(未来的未来) 每个Unity的开发者应该都对协同程序非 ...
- Unity 中的协同程序
今天咱就说说,协同程序coroutine.(这文章是在网吧敲的,没有unity,但是所有结论都被跑过,不管你信得过我还是信不过我,都要自己跑一下看看,同时欢迎纠错)先说说啥是协程:协同程序是一个非常让 ...
- Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
Lua学习笔记4. coroutine协同程序和文件I/O.错误处理 coroutine Lua 的协同程序coroutine和线程比较类似,有独立的堆栈.局部变量.独立的指针指令,同时又能共享全局变 ...
- Lua 学习笔记(九)协同程序(线程thread)
协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...
随机推荐
- spring mvc 通过配置xml访问控制器的三种方式
(一)通过 name 来一一映射(默认) (二)通过简单url 来指定映射,key 表示访问url value 是bean的ID (三)通过控制类的类名控制器,访问时类名首字母需要小写 <!-- ...
- ASP.net的url重写
http://blog.csdn.net/windok2004/article/details/2432691 1. 有关于URL的重写,本文也只是拿来主意.相继有MS的组件“URLRewriter” ...
- HBase 压缩算法设置及修改
Compression就是在用CPU换IO吞吐量/磁盘空间,如果没有什么特殊原因推荐针对Column Family设置compression,下面主要有三种算法: GZIP, LZO, Snappy, ...
- [R语言]foreach和doParallel包实现多个数据库同时查询
R语言在进行数据库查询时,每执行一条语句,都会阻塞.直到查询语句返回结果之后,才会进行下一条语句. 为了能够实现同时对多个数据库进行查询,以节省顺序执行下来的时间,首先考虑通过多线程来进行数据库查询. ...
- 洛谷 P1330 封锁阳光大学 Label:染色问题
题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构成的无向图,N个点之间由M ...
- JavaScript进阶(三)之对象
返回星期方法 getDay() 返回星期,返回的是0-6的数字,0 表示星期天.如果要返回相对应“星期”,通过数组完成,代码如下: <script type="text/javascr ...
- java8 引进lamda
就像泛型能使开发人员对数据类型进行抽象,Lambda的目的是让程序员能够对程序行为进行抽象. 你可以这样想,它能够让程序员把一段程序代码当做数据一样使用.一个方法可以像定义和使用一个变量那样的方式被定 ...
- 集成IOS 环信SDK
集成IOS SDK 在您阅读此文档时,我们假定您已经具备了基础的 iOS 应用开发经验,并能够理解相关基础概念. 下载SDK 通过Cocoapods下载地址 不包含实时语音版本SDK(EaseMobC ...
- vsfptd
如果想通过vsftpd来在主机和虚拟机之间拿数据,可以通过这种方法: 在主机的资源管理器中输入:ftp://虚拟机里面Linux的IP(如192.168.2.112)/ 如果反过来,需要如下:ftp: ...
- be supposed to
be supposed to 期望; 認為必須, 認為應該; 認為...... 期望; 認為必須, 認為應該; 認為...必要 Am I supposed to clean all the rooms ...