在Unity中StartCoroutine/unity yield returnn这个模式到底是怎么应用的

泻药!我从C/C++转向Unity的C#过程中,StartCoroutine/yield return 也是我一开始没弄明白的东西之一。我在网上收集资料的过程中,有两篇文章是让我有醍醐灌顶的感觉的。在此拾人牙慧,希望
能够帮到你。
说到Coroutine,我们必须提到两个更远的东西。在操作系统(os)级别,有进程(process)和线程(thread)两个(仅从我们常见的讲)实际的“东西”(不说概念是因为这两个家伙的确不仅仅是概念,而是实际存在的,os的代码管理的资源)。这两个东西都是用来模拟“并行”的,写操作系统的程序员通过用一定的策略给不同的进程和线程分配CPU计算资源,来让用户“以为”几个不同的事情在“同时”进行“。在单CPU上,是os代码强制把一个进程或者线程挂起,换成另外一个来计算,所以,实际上是串行的,只是“概念上的并行”。在现在的多核的cpu上,线程可能是“真正并行的”。Coroutine,翻译成”协程“,初始碰到的人马上就会跟上面两个概念联系起来。直接先说区别,Coroutine是编译器级的,Process和Thread是操作系统级的。Coroutine的实现,通常是对某个语言做相应的提议,然后通过后成编译器标准,然后编译器厂商来实现该机制。Process和Thread看起来也在语言层次,但是内生原理却是操作系统先有这个东西,然后通过一定的API暴露给用户使用,两者在这里有不同。Process和Thread是os通过调度算法,保存当前的上下文,然后从上次暂停的地方再次开始计算,重新开始的地方不可预期,每次CPU计算的指令数量和代码跑过的CPU时间是相关的,跑到os分配的cpu时间到达后就会被os强制挂起。Coroutine是编译器的魔术,通过插入相关的代码使得代码段能够实现分段式的执行,重新开始的地方是yield关键字指定的,一次一定会跑到一个yield对应的地方。对于Coroutine,下面是一个实现的function,里面的片段被yield关键字分成2段:IEnumerator YieldSomeStuff()
yield "hello";
Console.WriteLine("foo!");
yield "world";
推进的代码(模拟,非实际):IEnumerator e = YieldSomeStuff();
while(e.MoveNext())
Console.WriteLine(e.Current);
以此来推进整个代码片段的分段执行。更详细的分析如 的文章里提到。这里只要说明的是,对于Coroutine,是编译器帮助做了很多的事情,来让代码不是一次性的跑到底,而不是操作系统强制的挂起。代码每次跑多少,是可预期的。但是,Process和Thread,在这个层面上完全不同,这两个东西是操作系统管理的。在unity中,StartCoroutine这个方法是个推进器。StartCoroutine会发起类似上面的while循环。因为是while循环,因此,Coroutine本身其实不是“异步的”。Coroutine在整个Unity系统的位置,下面一张图可以说明:注:图片来自Unity官方文档里也写到"Normal Coroutine在Update之后"的字眼,如下内容第一行:Normal coroutine updates are run after the Update function returns. A coroutine is a function that can suspend its execution (yield) until the given YieldInstruction finishes. Different uses of Coroutines:
The coroutine will continue after all Update functions have been called on the next frame.
yield WaitForSeconds(2); Continue after a specified time delay, after all Update functions have been called for the frame
yield WaitForFixedUpdate(); Continue after all FixedUpdate has been called on all scripts
yield WWW Continue after a WWW download has completed.
yield StartCoroutine(MyFunc); Chains the coroutine, and will wait for the MyFunc coroutine to complete first.
由上面的图和文字可以大致猜测,.net虚拟机在每一帧循环中,会依次进入每个编译器预定义好的入口。对于Coroutine,编译器需要产生一些代码,在每次的大循环中,Unity的Update()返回后,保证是yield后的代码被正确调用,这样就形成了我们看到的一个function能分段执行的机制。
不要被楼上那么多话吓到。不要去理解进程线程以及任务等。Coroutine的参数都是IEnumerator类型的,你看下这个interface,他有Current属性,MoveNext方法,实际上操作类似foreach,即每次movenext下,得到current,执行下current,然后等下一帧被调用,执行过程还是如此,直到MoveNext返回false,表示执行完毕了,释放掉IEnumerator即可。所以,你可以弄个GameObejct试验下,给他弄个Coroutine,然后半路把这个GameObejct杀了,你会发现Coroutine虽然没执行完,但也没了,因为没人再去调用了。很好理解的东西
网络游戏技术总监在Unity中StartCoroutine/yield return这个模式到底是怎么应用的_百度知道
在Unity中StartCoroutine/yield return这个模式到底是怎么应用的
我有更好的答案
按默认排序
//blog.csdn.net/huang9012/article/details/" target="_blank">http://blog.csdn<a href="http
其他类似问题
yield的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁主题 : 关于yield 延时的奇怪问题。
级别: 新手上路
可可豆: 320 CB
威望: 320 点
在线时间: 38(时)
发自: Web Page
来源于&&分类
关于yield 延时的奇怪问题。&&&
上面是官方例程using UnityEusing System.Cpublic class example :
{IEnumerator WaitAndPrint() {yield return new (5);print(&WaitAndPrint & + );}IEnumerator Awake() {print(&Starting & + );yield return WaitAndPrint();print(&Done & + );}}这东东不能跑,说什么是Awake() 不能是 IEnumerator& 这倒没有什么,我改了一下&&&& IEnumerator WaitAndPrint()&&&& {&&&&&&&& yield return new WaitForSeconds(5);&&&&&&&& print(&WaitAndPrint & + Time.time);&&&& }&&&&& void Awake()&&&& {&&&&&&&& StartCoroutine(Shoot());&&&& }&&&& IEnumerator Shoot()&&& {&&&&&&& print(&Starting & + Time.time);&&&&&&& yield return WaitAndPrint();&&&&&&& print(&Done & + Time.time);&&&&&&& yield return new WaitForSeconds(1);}这东东理论上输出的结果是// - prints &Starting 0.0&// - prints &WaitAndPrint 5.0&// - prints &Done 5.0&但是我实际的输出结果是// - prints &Starting 0.0&// - prints &Done 0.01&根本就没有调用& WaitAndPrint();试过很多方法,好象yield& 这东东不能够嵌套使用。。。。不会是这样吧,不能嵌套使用 本人一个程序里就必需嵌套使用。。。。那位,哥们研究过这个没有?
级别: 新手上路
可可豆: 320 CB
威望: 320 点
在线时间: 38(时)
发自: Web Page
使用js 测试却发现一切正常。
function Awake(){StartCoroutine(swake());}function swake(){print (&Starting & + Time.time);// Start function WaitAndPrint as a coroutineyield WaitAndPrint();print (&Done & + Time.time);}function WaitAndPrint () {&&&&// suspend execution for 5 seconds&&&&yield WaitForSeconds (5);&&&&print (&WaitAndPrint &+ Time.time);}使用js 测试却发现一切正常。纳闷中。。。。
级别: 论坛版主
可可豆: 40085 CB
威望: 40085 点
在线时间: 1688(时)
发自: Web Page
1:c#代码字真小..2:我只会js.3:把IEnumerator换成void.4:帮顶&&&& IEnumerator WaitAndPrint()&&&& {&&&&&&&&print (&WaitAndPrint&);&&&&&&&& yield return new WaitForSeconds(5);&&&&&&&& print(&WaitAndPrint & + Time.time);&&&& }&&&&&&void Awake()&&&& {&&&&&&&&print(&hi&);&&&&&&&& StartCoroutine(Shoot());&&&& }&&&& IEnumerator Shoot()&&&&{&&&&&&&&print(&Starting & + Time.time);&&&&&&&&StartCoroutine(WaitAndPrint());&&&&&&&&print(&Done & + Time.time);&&&&&&&&yield return new WaitForSeconds(1);&&&&}[ 此帖被四角钱在 09:20重新编辑 ]
我的博客:QQ:3122828,微博:@unity3
级别: 侠客
可可豆: 1340 CB
威望: 1340 点
在线时间: 25(时)
发自: Web Page
&&&&&&&&yield return WaitAndPrint();这个写法不对,改成StartCoroutine(WaitAndPrint());
关注本帖(如果有新回复会站内信通知您)
iPhone5的分辨率? 正确答案:
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版

我要回帖

更多关于 unity yield return 的文章

 

随机推荐