【转】关于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差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...
随机推荐
- C# 词法分析器(一)词法分析介绍 update 2014.1.8
系列导航 (一)词法分析介绍 (二)输入缓冲和代码定位 (三)正则表达式 (四)构造 NFA (五)转换 DFA (六)构造词法分析器 (七)总结 虽然文章的标题是词法分析,但首先还是要从编译原理说开 ...
- dotnet core 初试两个小问题解决
1. Setup has detected that visual studio 2015 update 3 may not be completely installed 在安装 DotNetCor ...
- Only Link: Reading links for button/a etc
When To Use The Button Element: https://css-tricks.com/use-button-element/ The Difference Between An ...
- java 程序中添加socks 5代理
在需要使用代理的地方添加如下code: System.getProperties().put("socksProxySet","true"); System.g ...
- Spring In Action ②
初始化和销毁Bean init-method && destory-method <bean id="auditorium" class="test ...
- 20145304 Java第九周学习报告
20145304<Java程序设计>第九周学习总结 教材学习内容总结 JDBC简介 JDBC全名Java DataBase Connectivity,是Java联机数据库的标准规范.定义了 ...
- HDU3068最长回文 题解
题目大意: 求字符串的最长回文子串的长度. 思路: Manacher板题,Hash可能会T.要学习Manacher,可参考https://www.felix021.com/blog/read.php? ...
- 【wikioi】1003 电话连线
题目链接 算法: 最小生成树 PS:被卡过2天(中间的时间没去做).日期:2013-09-13 13:49:47 ~ 2013-09-17 13:01:07 此题为基础题 刚开始学图论时只会用Krus ...
- NOI模拟 热身赛T1
设p(m)的值为m的正因数个数(包括1和m本身)给定n,求满足p(x)=n的最小x. 简直弱到不行了... VW做法: 其实蛮简单的,然而想的时候忽略了指数是不增的 然后你以为做完了吗? 愚蠢的贡献了 ...
- 在Eclipse中使用JSHint检查JavaScript
之前使用 JSlint 来校验 JavaScript 代码,发现灵活性不够,因此改用 JSHint.按照官方的说法,JSHint 是一个社区驱动(community-driven)的工具,用于检测Ja ...