Unity中coroutine问题的示例分析

这篇文章主要介绍了Unity中coroutine问题的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

成都创新互联主要从事成都网站建设、成都做网站、网页设计、企业做网站、公司建网站等业务。立足成都服务隆尧,十多年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:028-86922220

1、从表面看协程的执行顺序

一个最简单的协程函数:

IEnumerator Test()
{
    yield return new WaitForSeconds(1);
    Debug.Log("End");
}

// 在其它地方StartCoroutine(Test());

作用:当你在其它地方执行了StartCoroutine(Test());之后,1秒之后打印“End”。

在开启协程之后,Test何时被调用?答案其实是每帧都要调用一次。(对迭代器函数来说,意思是每帧继续执行一次)。

如果每帧都继续,那么Test为什么最终在一秒后继续执行呢?答案在WaitForSeconds里面。

流程是这样的:

1、在StartCoroutine(Test())里,Test第一次被执行,yield中止并返回一个“WaitForSeconds(1)”对象。

2、执行StartCoroutine时,Unity内部注册这个Test函数。因为之后每帧都要调用,Unity内部先记下来。

3、这里,返回的WaitForSeconds(1)其实是一个小花招,它的设计思路是:

如果(Time.time小于之前说好的时间)
{
    返回:没结束;
}
返回:结束了,继续。

// 这里用伪码表示,想知道原理可以看后面的Unity官方说明文档

4、记住:协程函数每帧都要调用一次。于是Unity引擎层在这一秒,每帧都调用Test函数,重复了几十次,每次都被WaitForSeconds挡住,无法往下执行。

5、直到某一次调用,时隔1秒后了,WaitForSeconds终于放行了,Test才有机会继续执行,打印“End”。

这就是以WaitForSeconds为例解释的,协程的执行流程,以及等待1秒的原理。

2、解释yield return www;

现在可以回到题主问题了,其实yield return www 和 yield return new WaitForSeconds(1)是完全一样的道理,WWW的设计是:

如果(网络请求还在进行中)
{
    返回:没结束;
}
返回:结束了

同样的方式,如果网络请求没完成,那么你的协程函数就会被www阻拦住。这样就巧妙实现了一种异步机制,整个游戏不会因为www而卡住。

3、Unity如何做到这一点的?

eldereal 的回答很详细,其实C#根本就不支持真正的协程,而只支持迭代器。

由于游戏引擎的特殊性(每帧更新),Unity很巧妙的把迭代器改装成了一个似乎能并行执行的东西,也确实很好用。

别忘了,WWW和WaitForSeconds都是Unity提供的类,并不是C#原本就支持的。如果你很好奇,想扩展出自己的类似WWW的类,参考官方文档自定义Yield对象:

CustomYieldInstruction

https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html

由于Unity的这种“伪”协程属于自己制定的方案,未来引擎更新时候甚至会修改设计,所以理解调用顺序和大致原理更重要,不要拘泥于代码本身。

4、其它说明

Unity的Coroutine机制设计的很好,就是这个名字起的太有问题了,无论英文的Coroutine和中文的协程,都很不合适。

有一定golang、python gevent、skynet开发经验的人(主要是服务器端的),都对协程有较好的理解,而Unity的协程与真正的协程差异太大了。起同样的名字带来很大的误导作用,交流也很困难。

一句话解释Unity协程:其实Unity的Coroutine在我看来,更像是“注册一个 每帧都调用的函数”,只不过这个函数支持yield中止,仅此而已。

感谢你能够认真阅读完这篇文章,希望小编分享的“Unity中coroutine问题的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持创新互联,关注创新互联行业资讯频道,更多相关知识等着你来学习!


分享文章:Unity中coroutine问题的示例分析
链接URL:http://azwzsj.com/article/jcpheg.html