深入浅出!从语义角度分析隐藏在Unity协程背后的原理
Unity的协程使用起来比较方便,但是由于其封装和隐藏了太多细节,使其看起来比较神秘。比如协程是否是真正的异步执行?协程与线程到底是什么关系?本文将从语义角度来分析隐藏在协程背后的原理,并使用C++来实现一个简单的协程,以揭开协程的神秘面纱。(文内代码为截图,可点击放大查看。)
一、什么是协程
简单来说,协程是一个有多个返回点的函数。一般来说一个函数只有一个返回点,函数的调用者调用一次后,函数的生命周期就结束了。而对于协程来说,其生命周期由调用者来决定,可以通过返回值来决定如何进行一次调用以及如何结束调用。
由于协程返回的是一系列的值,每一个yield return对应一次返回。用迭代器作为返回类型是比较好的选择,可以简单的认为每一个yield return对于了迭代器中的一个元素。
Unity的C#代码中一个协程的返回值通常是IEnumerator类型,IEnumerator 接口有两个方法,分别是 Current 和 MoveNext。我们可以简单的认为:协程就是一个返回迭代器的函数,一开始迭代器的Current指向函数的开头,每执行一次MoveNext,Current就指向下一个yield return 返回的值。例如:
二、协程的核心,神奇的yield
我们来看看上而代码示例中的函数coroutine:
上面代码神奇的地方在于关键词yield,为什么可以调用多次yield return返回一组值,并且该函数的返回值变成了Enumerator类型?这其实就是隐藏在协程背后的核心原理。有很多关于协程的核心原理的分析及实现的文章,大多都是从系统底层的角度来分析,使用了汇编,goto语句或者是C 语言的 setjmp 和 longjmp来实现了协程,虽然分析得比较透彻,但对读者所掌握的知识要求比较高,其中的一些概念比较晦涩,难于理解。
实际上从语义角度来看,协程的工作原理比较简单,任何支持闭包的语言都可以实现协程。下面我们从语义的角度来解释协程:
1.每一个yield return被包装成一个函数(简称为Y函数),如果该函数使用了外层的局部变量,将形成一个闭包
2.Y函数的返回值为yield传入的对象和下一个yield return所包装成的函数
3.对迭代器的MoveNext调用等价于对Y函数的调用
4.最后一个yield return包装成的Y函数返回yield传入的对象和一个空函数以代表迭代结束(即调用MoveNext时返回false)
三、简单协程的C++实现
以下是根据协程在语义上的解释,用C++的实现一个简单协程示例:
一共不到60行代码,就实现了简单的协程。对于上示例中的coroutine函数,除了语法上有一些差异,语义已经和C#的协程完全一协了,甚至我们可以引入一个宏让其长得更像C#的协程,例如:
虽然以上代码段看起来已经比较像Unity的协程了,但是遗憾的是代码还不够简洁,有一点点语法噪音(函数的结尾部分多了一些没意义的括号)语法也不够统一(最后一行是return yield)。
四、For循环
第三节我们讲了协程的简单的实现,但是如果我们如果在for循环中使用yield还存在问题,比如以下代码段:
coroutine1函数返回的迭代器中只包含一个值1,而不是我们期望的1~10。因此对于协程中的循环我们需要特殊处理。分析以上代码,我们期望的是对于循环中的每一个i,调用yield生成一个coroutine node,然后将这些node合并成一个链表返回。因此我们可以将协程中的for语句翻译成一个For函数,代码如下:
Combine函数实现将两个Coroutine Node连接在一起合并成一个链表返回,其定义代码如下:
有了For函数,可以将coroutine1实现可以改成如下:
虽然在语法上该函数有一些丑,但是是从语义上完全是等价以下C#代码的:
以下是一个更加复杂的示例:
语义上等价的C#代码为:
五、总结
本文从语义的角度来解释了协程的运行机制,并使用C++实现了简单的协程,但仍有部分内容未讨论到,比如怎样在For循环中实现break,yield break等,其实要实现这些并不困难,感兴趣的同学可以自行去研究。
回到引言中提到的两个问题:
协程是否为异步执行?严格意义上来讲,协程并不是异步执行的,但是调用者可以分时间片去执行每一个yield,让程序看起来像是异步的。协程和线程是什么关系?协程与线程之间没有严格的对应关系,但是可以结合使用,隐藏一些不必要的细节以简化编程,比如unity的WWW。
来源:公众号<Gad-腾讯游戏开发者平台>
作者:Tseclam
原题:程序|深入浅出!从语义角度分析隐藏在Unity协程背后的原理
产品经理必读文章
一份鹅厂产品经理自我成长的文档
腾讯内部培训手册:产品经理晋升路上的那些坎儿
重磅干货|QQ运营女王:小白到大神,要跨过哪些坑
不声不响我就当了产品经理......
腾讯产品法则:从需求分析到需求管理,做产品需求最全的方法都在这了
为何有些产品经理画的线框图总被吐槽
什么是「好产品」?
陈会华:写给喜欢数据分析的初学者
体验至上的时代,交互设计师能为游戏做点什么?
熊一冬:做网游不是开宝箱-产品运营大循环思
深入浅出!从语义角度分析隐藏在Unity协程背后的原理的更多相关文章
- 聊一聊Unity协程背后的实现原理
Unity开发不可避免的要用到协程(Coroutine),协程同步代码做异步任务的特性使程序员摆脱了曾经异步操作加回调的编码方式,使代码逻辑更加连贯易读.然而在惊讶于协程的好用与神奇的同时,因为不清楚 ...
- Unity协程(Coroutine)原理深入剖析
Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 其实协程并没有那么复杂,网上很多地方都说是多 ...
- Unity协程(Coroutine)原理深入剖析(转载)
记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield r ...
- 【转】Unity协程(Coroutine)原理深入剖析
Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网 ...
- Unity协程(Coroutine)管理类——TaskManager工具分享
博客分类: Unity3D插件学习,工具分享 源码分析 Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...
- Unity协程(Coroutine)原理深入剖析再续
Unity协程(Coroutine)原理深入剖析再续 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 前面已经介绍过对协程(Coroutine ...
- Unity 协程运行时的监控和优化
我是快乐的搬运工: http://gulu-dev.com/post/perf_assist/2016-12-20-unity-coroutine-optimizing#toc_0 --------- ...
- unity协程coroutine浅析
转载请标明出处:http://www.cnblogs.com/zblade/ 一.序言 在unity的游戏开发中,对于异步操作,有一个避免不了的操作: 协程,以前一直理解的懵懵懂懂,最近认真充电了一下 ...
- Unity协程Coroutine使用总结和一些坑
原文摘自 Unity协程Coroutine使用总结和一些坑 MonoBehavior关于协程提供了下面几个接口: 可以使用函数或者函数名字符串来启动一个协程,同时可以用函数,函数名字符串,和Corou ...
随机推荐
- 【Unity_UWP】Unity 工程发布win10 UWP 时的本地文件读取 (下篇)
Universal Windows Platform(UWP)是微软Windows10专用的通用应用平台,其目的在于在统一操作系统下控制所有智能电子设备. 自从Unity 5.2之后,配合VS 201 ...
- 跟据经纬度实现附近搜索Java实现
现在很多手机软件都用附近搜索功能,但具体是怎么实现的呢>在网上查了很多资料,mysql空间数据库.矩形算法.geohash我都用过了,当数据上了百万之后mysql空间数据库方法是最强最精确的(查 ...
- echarts地图定时切换散点及多图表级联联动
本文目录 1. 摘要 2.引入ECharts以及地图相关json 3. 界面布局 4. js实现图形布局 5.定时循环jquery实现 6. 总结 1. 摘要 最近做项目遇到个统计相关需求,一个页面 ...
- selenium自动测试
import requestsimport sysimport iofrom selenium import webdriverfrom selenium.webdriver.common.actio ...
- 社会地位即服务, Status as a Service (一): 社交网络是一种 ICO 行为?
上周,看到 Eugene Wei 又发了一篇长文,Status as a Service (StaaS).状态即服务?服务器的状态吗?不知所言.抱着好奇,我打开了这篇文章,一看就是 3 个小时!
- 【教程】Tomcat 的catalina.out 日志按照自定义日期格式进行切割
本文简单介绍在使用cronolog对tomcat的日志进行自定义日期格式的切割,方便日志的整理和遇到问题日志的排查! 安装cronolog 安装cronolog的方法网上有很多,这里也简单的介绍一下. ...
- 以管理员身份运行CMD
To complete these procedures, you must be a member of the Administrators group. To start a command p ...
- bootstrap css-网格系统
前言:第一次记录点东西,只能勉强算是笔记吧.博主自学前端,深知自己水水的,但还是向把自己学到的东西记录下来,这不刚学习了bootstrap的css部分,现在整理出笔记. 1,Bootstrap网格系统 ...
- CF1065E Side Transmutations
link 题意: 给你一个长为m的序列$b_i$,定义两个字符串a,b相同当前仅当a执行以下操作后能变成b:($\rm{prefix}(x,y)$及$\rm{suffix}(x,y)$定义为串x的前/ ...
- zoj 3647 智商题
此题就是求格点中三角形的个数. 就是找出三点不共线的个数. n*m的矩形中有(n+1)*(m+1)个格点. 选出三个点的总个数为:C((n+1)*(m+1),3). 减掉共线的情况就是答案了. 首先是 ...