电脑打游戏出现error,wrong worknew threadd ni gamethreadproce

不要找书,直接去油管找视频。&br&入门推荐VTC的视频教程VTC.Introduction.to.Game.Development.Using.Unity.3D(从0开始讲解实例。优点是内容宽泛容易理解,缺点是版本较早,深度不够。作为刚接触3D通用引擎的入门很好)&br&也有官方推荐的MikeGeig出品的系列,传送门在此: &a href=&//link.zhihu.com/?target=http%3A//unity3d.com/learn/live-training& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unity - Learn&/a&
不要找书,直接去油管找视频。 入门推荐VTC的视频教程VTC.Introduction.to.Game.Development.Using.Unity.3D(从0开始讲解实例。优点是内容宽泛容易理解,缺点是版本较早,深度不够。作为刚接触3D通用引擎的入门很好) 也有官方推荐的MikeGeig出品的系列,…
&p&一&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-fdd6f2aea566f66a01b1_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic1.zhimg.com/50/v2-fdd6f2aea566f66a01b1_r.jpg&&&/figure&&p&高自由度,所有装备都自己做,所有材料都是自己打。&/p&&p&本来很有趣的游戏,但是对新手极为不友好,因为不看攻略,你什么都不知道。就算大佬,也怕同为玩家的人背后捅刀。&/p&&p&小游戏却把末日生存体现的淋漓尽致。&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-14d4ac941c90a16c4dbe38_b.jpg& data-rawwidth=&1196& data-rawheight=&768& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1196& data-original=&https://pic2.zhimg.com/50/v2-14d4ac941c90a16c4dbe38_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&二&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-26da958fc911b4f9eeda12_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic1.zhimg.com/50/v2-26da958fc911b4f9eeda12_r.jpg&&&/figure&&p&手机魔兽并非浪得虚名,相比于国产MMORPG手游,甩几条街,自由度相当高,系统各方面都很完善。&/p&&p&当然需要大佬带,你才能体验到游戏真正的乐趣。&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-a923b86bc_b.jpg& data-rawwidth=&2048& data-rawheight=&1536& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&https://pic1.zhimg.com/50/v2-a923b86bc_r.jpg&&&/figure&&p&&br&&/p&&p&三&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-1c5acfa00c6a83a8a00b9eb0d88cd515_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic3.zhimg.com/50/v2-1c5acfa00c6a83a8a00b9eb0d88cd515_r.jpg&&&/figure&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-775535dac164f48d140a5bedff2826b5_b.jpg& data-rawwidth=&1024& data-rawheight=&600& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&https://pic1.zhimg.com/50/v2-775535dac164f48d140a5bedff2826b5_r.jpg&&&/figure&&p&强烈推荐,我的世界衍生品中我认为最好的一款,点一下玩一年,上天入地,杀龙灭鬼,基本上你玩过的RPG元素,这个游戏都有。&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-f028e984fc7e570ccf444e_b.jpg& data-rawwidth=&800& data-rawheight=&480& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic4.zhimg.com/50/v2-f028e984fc7e570ccf444e_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&更新&/p&&p&下载APP&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-fa5add4c16f5c8f56762_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic1.zhimg.com/50/v2-fa5add4c16f5c8f56762_r.jpg&&&/figure&&p&百度上有,最好去官网下载,验证有点复杂,但是这个APP基本上谷歌游戏全都有,而且不需要挂VPN。&/p&&p&游戏&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-463c0afe7c14c86c51b9_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic3.zhimg.com/50/v2-463c0afe7c14c86c51b9_r.jpg&&&/figure&&p&很有趣,很耐玩,生孩子,探索,管理人员,细节乐趣很多。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-ce00b3d3a346fe30bcc4_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic3.zhimg.com/50/v2-ce00b3d3a346fe30bcc4_r.jpg&&&/figure&&p&大作,无需多言,无双还是人性,取决于你的一念之间。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-7eccc0d401a578b24b09ec499dba482c_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic4.zhimg.com/50/v2-7eccc0d401a578b24b09ec499dba482c_r.jpg&&&/figure&&p&&br&&/p&&p&高画质,打僵尸为主体,但是探索趣味也不错。&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-43e0a341e53c7bb8b92db57f72be8af1_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic1.zhimg.com/50/v2-43e0a341e53c7bb8b92db57f72be8af1_r.jpg&&&/figure&&p&开罗系列,真的是点一下玩一年,根本停不下来。&/p&&p&&br&&/p&&p&大家说的,&/p&&p&我的世界,人尽皆知,不多说。&/p&&p&创造与魔法,这游戏只是刚开始大家都不会才好玩,现在呵呵。&/p&&p&&br&&/p&&p&&br&&/p&&p&再度更新&/p&&p&更新一波我TM吹爆的游戏&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-f187ffdf6f3_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic4.zhimg.com/50/v2-f187ffdf6f3_r.jpg&&&/figure&&p&打僵尸,爆装备,解密,撸树,撸石头,偷别人家。自己修家,建防御,虽然这游戏很复杂,很肝,但是它就是TM好玩。&/p&&p&&br&&/p&&p&下面就是我TM吹爆系列&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-f7683fbe59be741081dd_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic3.zhimg.com/50/v2-f7683fbe59be741081dd_r.jpg&&&/figure&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-fb08bd1fcee272ca3f1205_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic1.zhimg.com/50/v2-fb08bd1fcee272ca3f1205_r.jpg&&&/figure&&p&4年前我就玩过,啊!这山,这水,这光,最主要还是单机,无需氪金,剧情反正我是没看懂,但是我就是要吹爆。&/p&&p&手机版上古卷轴,武器,技能,庞大的开放世界,对于当时还在玩2D游戏的我,简直是神作,当然现在看来我也觉得是神作。NPC完善,巨大的城镇,任务趣味性,真的,要不是现在没空,我肯定会找来再玩一次。&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-b16d9108923beddefea167_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic4.zhimg.com/50/v2-b16d9108923beddefea167_r.jpg&&&/figure&&p&高级版泰拉瑞亚,都是挖矿,只不过是高科技挖矿,当然因为没中文,我当时并没有久玩。但是它有不输与泰拉瑞亚的乐趣性,对了,当时它名字貌似叫“火星救援”。&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-7ce442c5e6a2329aed6b03_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic1.zhimg.com/50/v2-7ce442c5e6a2329aed6b03_r.jpg&&&/figure&&p&3年前的游戏,第三人称设计版上古卷轴+死亡空间。但BUG太多,而且任务太难,毕竟手机上的射击游戏,操作不好加装备烂,真的会被锤爆。&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-1c22acddd410b352f10d22_b.jpg& data-rawwidth=&854& data-rawheight=&480& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&854& data-original=&https://pic4.zhimg.com/50/v2-1c22acddd410b352f10d22_r.jpg&&&/figure&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-c4765ea43cbd3ddfce0b5_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic2.zhimg.com/50/v2-c4765ea43cbd3ddfce0b5_r.jpg&&&/figure&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-fa50a933ecf4_b.jpg& data-rawwidth=&1080& data-rawheight=&1920& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic3.zhimg.com/50/v2-fa50a933ecf4_r.jpg&&&/figure&&p&以上这些游戏都是同一个厂商出的,全是精品呀,这2个老游戏是因为当时不知道什么原因黑屏,没玩过,所以不好评价。&/p&&p&&br&&/p&&p&TAPTAP上这些游戏都无法下载,我只是推荐,毕竟真的没空去找资源,我能尽力就是上面推荐的那个APP应该会有资源,实在不行求助贴吧老哥吧!对不起,各位。&/p&
一高自由度,所有装备都自己做,所有材料都是自己打。本来很有趣的游戏,但是对新手极为不友好,因为不看攻略,你什么都不知道。就算大佬,也怕同为玩家的人背后捅刀。小游戏却把末日生存体现的淋漓尽致。 二手机魔兽并非浪得虚名,相比于国产MMORPG手游,…
&figure&&img src=&https://pic4.zhimg.com/v2-b0e25f372e3d7331ff6eaf444b0448c6_b.jpg& data-rawwidth=&640& data-rawheight=&394& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic4.zhimg.com/v2-b0e25f372e3d7331ff6eaf444b0448c6_r.jpg&&&/figure&&p&&b&从柏林诠释说起&/b&&/p&&p&在2008年召开的国际Roguelike开发会议上,众多的Roguelike开发者与爱好者共同制定了《&a href=&http://link.zhihu.com/?target=http%3A//www.gamesetwatch.com/2009/12/column_play_the_berlin_interpr.php& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&柏林诠释&/a&》,规定了Roguelike游戏需要具备如下的重要元素:&/p&&ul&&li&游戏使用&b&过程生成地图&/b&来增加可重玩性。&/li&&li&游戏的角色会&b&永久死亡&/b&,存档无法用来从永久死亡状态恢复角色。&/li&&li&游戏采用&b&回合制&/b&、&b&网格化地图&/b&,玩家可以有足够的时间思考每一步的决策。&/li&&li&游戏&b&非模式化&/b&,玩家可以采取的行动不根据游戏的状态而变化。&/li&&li&游戏路线&b&非线性&/b&,玩家可以用不同的手段来达成相同的游戏目标。&/li&&li&游戏具备资源管理玩法,玩家必须合理配置其资源的消耗来最大化生存的可能。&/li&&li&游戏专注于怪物战斗,玩家没有和平选项来跳过战斗。&/li&&li&游戏鼓励玩家探索地图来获取随机分布在地图上的各类道具。&/li&&/ul&&p&除此之外,Roguelike游戏还往往包括如下的次要元素:&/p&&ul&&li&玩家采用单一角色通关游戏。&/li&&li&怪物具备一些和玩家相同的能力,如与场景道具互动,施放法术等。&/li&&li&游戏具备战术上的挑战,迫使玩家需要尝试很多次才能学会最适合的生存战术。&/li&&li&游戏采用ASCII字符表示的地块组成的地图。&/li&&li&游戏包含地下城探索,地下城由房间和连接房间的走廊组成。&/li&&li&游戏会将玩家角色的统计显示出来。&/li&&/ul&&p&&br&&/p&&p&然而,给游戏制定一个“标准”往往就是一个立flag的事情。当下所流行的,为我们所熟知的roguelike游戏中,有许多游戏不完全具备上述特点。我这里将一些steam上标有rogue-like标签的热门游戏列出来,与上述的柏林诠释进行比对:&/p&&p&《杀戮尖塔》(Slay the Spire):不完全具备网格化地图。&/p&&p&《死亡细胞》(Dead Cells):非回合制,不具备网格化地图。&/p&&p&《暗黑地牢》(Darkest Dungeon):不完全具备网格化地图。&/p&&p&《饥荒》(Don't Starve):非回合制,不专注于怪物战斗。&/p&&p&《以撒的结合》(The Binding of Isaac):非回合制。&/p&&p&《挺进地牢》(Enter the Gungeon):非回合制。&/p&&p&&br&&/p&&p&可以看出,回合制、网格化地图、ASCII字符地图等游戏元素带有深刻的时代烙印。随着机器性能的发展和开发工具的多样化,回合制和网格化地图不再是roguelike的必选项了,并且它们对roguelike的本质,对这一品类的核心乐趣,不具备足够的贡献度。真正能被继承下来的,是&b&随机生成游戏内容&/b&(Procedural Generation)+&b&永久死亡&/b&(Permadeath)+&b&资源管理&/b&(Resource Management)这三大核心要素。&/p&&p&可这三大核心要素,在太多的玩法迥异的游戏中都出现了。带有永久死亡元素的有P社游戏铁人模式,骑砍直面人生,Diablo专家模式等,在此基础上带有随机生成内容和资源管理的也有Minecraft,无人深空等等游戏的部分模式,而我们不可能把它们都称作Roguelike。这说明三大核心要素自己并不能构成核心玩法,这些游戏的核心玩法还是动作与战斗,是采集与建造,是策略,是解谜等。Roguelike元素能做的,是围绕这个核心玩法,给它添油加醋,创造出与常规玩法不同的体验。&/p&&p&&br&&/p&&p&那Roguelike游戏为何要把这三个要素放在一起呢?这些要素显然存在紧密的联系,我想先从永久死亡说起。&/p&&p&&br&&/p&&h2&&b&核心要素:永久死亡&/b&&/h2&&p&永久死亡的机制,是和存档系统密不可分的。存档系统主要分为检查点存档和即时存档。存档系统的初衷,是为了便于玩家恢复游戏状态,避免因非游戏因素(现实中出门办事/晚上睡觉)等被迫终止而带来损失,也是PVE游戏的一大优势。存档系统避免的损失,是玩家的游戏时间,是玩家必须重来的游戏部分。游戏设计中,让玩家重新去玩一部分一模一样的游戏内容只有一种原因:玩家没有消费完这部分内容,也就是没能成功掌握这部分内容。而存档系统在这里便可以限制最大失败惩罚,在玩家失败时让游戏恰好回溯到玩家未能掌握的内容之前,而不是让他从头玩一遍。&/p&&p&不过存档系统的存在,也限制了游戏设计中的风险设计。在现实中,任何可能引起的损失都会是风险的一部分;而在游戏里,由于存档这种回溯时间线的方法存在,只要损失达到玩家不可接受的程度,玩家都可以通过重来来回复。所以“永久死亡”机制,解决的就是风险设计的问题,把删档作为损失的一部分来增加坏决策的风险。与之相对的是,能让你继续玩下去的,就是好决策。坏决策和好决策共同组成了一个“决策池”(Decision Pool),让玩家从中去做有意义的选择。可如果游戏是单线式,何时何地出现什么怪物都是固定的,那永久死亡的作用,就变成了让玩家重新去玩一部分一模一样的游戏内容,这是非常伤害游戏体验的一件事情,这样的决策池,不也毫无惊喜了吗。&/p&&p&&br&&/p&&h2&&b&核心要素:随机内容&/b&&/h2&&p&为了避免上述问题,Roguelike需要引入随机地图以及其他过程生成内容,制造不确定性(Uncertainty),让每次开始游戏的所可能面对的体验都不尽相同。从叙事角度看,在每次游玩中玩家操纵的角色所经历过的一切“历史事件”都具备唯一性与不可回溯性;玩家在失去这个角色时,不仅失去了那段游戏时间的努力,也会永久失去那个角色所伴你度过的记忆。可以说过程生成系统及其带来的非线性体验,是永久死亡机制下,避免内容高度重复的一个手段。&/p&&p&上面说到的“决策池”,是玩家当下能进行的、对游戏会产生深远影响的行为总和,此前说到的Roguelike“非模式化”的特点,就是指游戏不会因当前状态与模式上的不同而使决策池发生根本变化。而决策池中,包含了好的决策与坏的决策,但不应该包含“明显好”的决策和“明显坏”的决策。根据&a href=&http://link.zhihu.com/?target=https%3A//www.gamasutra.com/blogs/BriceMorrison/733/Meaningful_Choice_in_Games_Practical_Guide__Case_Studies.php& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Meaningful Choice&/a&的观点,所有的决策收益都必须和当下的游戏状态紧密相连。而引入随机元素制造非线性体验的结果,便是玩家的可以得到的选择极难达成全局最优。永久死亡+随机因素在决策层面产生的影响,就是强迫玩家就必须接受“非最优”的选择无处不在这个事实,接受当下的局部最优解,减少玩家追求全局最优解的动力,把精力转向“继续游戏”这件事情上。&/p&&p&然而对于缺乏经验的玩家来说,如果在游戏中缺少前后的连接(Context)和显性的提示时,他是很难时刻分辨游戏的决策优劣的。因此,在roguelike游戏的高惩罚到来之时 ,他会倾向归因为“是这游戏没教会我,我才失败的”,而不是“我之前有几个决策做的不对,我才失败的”。这样的决策系统,即使玩家失败了,想要从头再来,学习如何掌握这样的游戏,也会因为缺少相关的线索而无从下手。&/p&&p&&br&&/p&&h2&&b&核心要素:资源管理&/b&&/h2&&p&资源管理系统,在这里就是决策对应的线索。游戏用资源对玩家的选项浅度量化,把决策的一部分引导到资源管理上,便于玩家从中学习和重来。一般意义上,虽然有随机因素的干扰,玩家消耗资源越多的地方,在这上面得到的帮助也越大;在玩家失败并接受删档惩罚的时候,可以从资源的角度分析失败的原因,从而在下次重来时重新配置资源分配。资源管理玩法,最怕出现的情况之一,是由于系统的简单化,让全局最优解可以很容易通过数值意义上迭代来逼近;而在Roguelike这里,随机生成的游戏内容恰好一定程度隐藏了全局最优解,帮助达到了延长游戏可重玩性的目的。&/p&&p&总的来说,符合Roguelike定义的游戏往往同时使用永久死亡、随机生成和资源管理玩法等要素,在一个外来的核心玩法的推动下,围绕决策的风险和收益,大大延长了游戏的可玩时间,并创造了独特的游戏体验。然而,上面提到的逻辑,也就是roguelike们想做到的事情,一直都能这么顺利的实现吗?&/p&&p&&br&&/p&&h2&&b&Roguelike并非完美&/b&&/h2&&p&在Roguelike游戏中,存在着诸多的技术和设计隐患,限制了往这一方向靠近的部分游戏作品的表现。最常见的之一便是存档系统的问题了。永久死亡机制高度依赖于存档,而大多数游戏的存档是存放于本地的,这意味着玩家只要乐意,是具备完全的解读和修改的能力的,隐藏存档位置和加密移位也只是延后了修改器的研发而已。只有逻辑和存档放在服务器端上的游戏,其永久死亡模式才可以说是完备的,但带来的成本也是不容忽视的。存档破解的选项存在意味着最大死亡惩罚在永久死亡模式下只是从重新读档变成了上网查看如何破解存档,哪怕干掉存档系统,内存修改器的存在也使其意义降低,而存档系统的缺失却会完全限制游戏的总通关时长。&/p&&p&存档问题,限制的其实是游戏拔高难度降低容错的能力。Roguelike还往往具备高度随机的关卡、怪物和奖励;在随机因素的作用下,非即时制的Roguelike游戏除了考验玩家的运气和对游戏的了解以外,很难有其他拔高难度的做法;而后者是会很快被玩家摸清的,导致高难度的回合制roguelike在压榨数值时,往往变成一个纯看脸的游戏。看脸的游戏结合高死亡惩罚会带来无效的重复劳动和糟糕的体验,这点爬过塔的同学应该深有体会。因此,基于存档系统的死亡惩罚高度依赖玩家的自觉前提下,从随机因素上制造难度只会挑战玩家的这种自觉,而对通关后的胜利体验帮助不大。&/p&&p&除此之外,大多数Roguelike的非线性游戏特点,也使其很难具备单线性和多线性游戏那样容易的叙事和&b&机制-叙事自洽&/b&(Ludonarrative Consistence)能力。以《永恒之柱》为代表的TRPG同样具备永久死亡模式作为可选项和丰富的资源管理玩法,但是为了突出剧情和与逻辑自洽的世界观设定,很难引入过程生成的游戏环境来制造可重玩性。在这一点上,《环世界》作为非线性“过程生成叙事”的代表,通过复杂而自洽的系统演示了高度过程生成的游戏如何创造与玩家存在紧密情感连接的有特点的角色;但它的殖民地管理的核心玩法使其无法完全归入Roguelike标签下,只能说是值得参考的另一种游戏设计的方向吧。总之,大多数Roguelike的关注方向,也并不在此。&/p&&p&其实一个游戏的机制-叙事自洽能力,从商业角度上能很大程度决定这个游戏与竞品相比的体验差异,给玩家一个选你而不是选别人的理由。Roguelike游戏们对这方面的关注度往往低于它们对核心玩法本身的打磨,但一旦打磨不成功便很难在同类中制造区分度,这也是许多打着Roguelike旗号本质换汤不换药的原因。《暗黑地牢》所引入的痛苦系统可以说是这个方向上比较成功的一次尝试,也算是替Roguelike游戏在摆脱柏林诠释的刻板印象,寻找新的突破口指明了方向吧。&/p&&p&&/p&&p&&/p&
从柏林诠释说起在2008年召开的国际Roguelike开发会议上,众多的Roguelike开发者与爱好者共同制定了《》,规定了Roguelike游戏需要具备如下的重要元素:游戏使用过程生成地图来增加可重玩性。游戏的角色会永久死亡,存档无法用来从永久死亡状态恢复…
&figure&&img src=&https://pic4.zhimg.com/v2-2f9c163cf6b_b.jpg& data-rawwidth=&900& data-rawheight=&500& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic4.zhimg.com/v2-2f9c163cf6b_r.jpg&&&/figure&&h2&作者:闲鱼技术福居&/h2&&p&&br&&/p&&p&在终端业务需求日益复杂,版本迭代日趋于频繁的情况下,我们迫切需要优秀的多端统一跨平台开发方案以提升研发效率。目前已有类似RN,Weex这种通过JavaScript桥接到Native的终端技术方案。但是,基于JavaScript的桥接模式有JavaScriptCore自身的性能瓶颈和桥接层的消耗。闲鱼产品界面的复杂度和我们制定的高性能基线使得我们无法选择这些方案。&/p&&p&目前我们正在积极尝试和探索Flutter在业务中的实践以追求更加高性能的跨平台终端方案。同为跨平台技术,Flutter为什么有其它方案所不具备的高性能特性?&/p&&p&&br&&/p&&p&&br&&/p&&ul&&li&Flutter在Rlease模式下直接将Dart编译成本地机器码,避免了代码解释运行的性能消耗。&/li&&/ul&&p&&br&&/p&&ul&&li&Dart本身针对高频率循环刷新(如屏幕每秒60帧)在内存层面进行了优化,使得Dart运行时在屏幕绘制实现如鱼得水。&/li&&/ul&&p&&br&&/p&&ul&&li&Flutter实现了自己的图形绘制避免了Native桥接。&/li&&/ul&&p&&br&&/p&&p&&br&&/p&&p&Flutter体系结构:&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-9d354ebf8a6ca24e9510c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1257& data-rawheight=&754& class=&origin_image zh-lightbox-thumb& width=&1257& data-original=&https://pic1.zhimg.com/v2-9d354ebf8a6ca24e9510c_r.jpg&&&/figure&&p&为了更好地应用和实践,我们需要深入到引擎内部去理解的它的实现原理和构造。线程一直是在开发当中令人比较头疼的话题,我们也在实践过程中踩过不少坑,本文就Flutter引擎的线程模式进行一些探讨。&/p&&p&&br&&/p&&blockquote&对于刚接触Flutter的朋友,更加详尽的Flutter相关信息可以浏览它的官方网站:&a href=&http://link.zhihu.com/?target=https%3A//flutter.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Flutter IO&/a&&/blockquote&&p&&br&&/p&&h2& Flutter 线程模型&/h2&&p&&br&&/p&&p&Flutter Engine自己不创建管理线程。Flutter Engine线程的创建和管理是由embedder负责的。Embeder指的是将引擎移植到平台的中间层代码。&/p&&p&Flutter Engine要求Embeder提供四个Task Runner。尽管Flutter Engine不在乎Runner具体跑在哪个线程,但是它需要线程配置在整一个生命周期里面保持稳定。也就是说一个Runner最好始终保持在同一线程运行。这四个主要的Task Runner包括:&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-91a0ef7b11155efa2d278e9ac4fb536d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&731& data-rawheight=&357& class=&origin_image zh-lightbox-thumb& width=&731& data-original=&https://pic2.zhimg.com/v2-91a0ef7b11155efa2d278e9ac4fb536d_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&h2& Platform Task Runner&/h2&&p&&br&&/p&&p&Flutter Engine的主Task Runner,运行Platform Task Runner的线程可以理解为是主线程。类似于Android Main Thread或者iOS的Main Thread。但是我们要注意Platform Task Runner和iOS之类的主线程还是有区别的。&/p&&p&对于Flutter Engine来说Platform Runner所在的线程跟其它线程并没有实质上的区别,只不过我们人为赋予它特定的含义便于理解区分。实际上我们可以同时启动多个Engine实例,每个Engine对应一个Platform Runner,每个Runner跑在各自的线程里。这也是Fuchsia(Google正在开发的操作系统)里Content Handler的工作原理。一般来说,一个Flutter应用启动的时候会创建一个Engine实例,Engine创建的时候会创建一个线程供Platform Runner使用。&/p&&p&跟Flutter Engine的所有交互(接口调用)必须发生在Platform Thread,试图在其它线程中调用Flutter Engine会导致无法预期的异常。这跟iOS UI相关的操作都必须在主线程进行相类似。需要注意的是在Flutter Engine中有很多模块都是非线程安全的。一旦引擎正常启动运行起来,所有引擎API调用都将在Platform Thread里发生。&/p&&p&Platform Runner所在的Thread不仅仅处理与Engine交互,它还处理来自平台的消息。这样的处理比较方便的,因为几乎所有引擎的调用都只有在Platform Thread进行才能是安全的,Native Plugins不必要做额外的线程操作就可以保证操作能够在Platform Thread进行。如果Plugin自己启动了额外的线程,那么它需要负责将返回结果派发回Platform Thread以便Dart能够安全地处理。规则很简单,对于Flutter Engine的接口调用都需保证在Platform Thread进行。&/p&&p&需要注意的是,阻塞Platform Thread不会直接导致Flutter应用的卡顿(跟iOS android主线程不同)。尽管如此,平台对Platform Thread还是有强制执行限制。所以建议复杂计算逻辑操作不要放在Platform Thread而是放在其它线程(不包括我们现在讨论的这个四个线程)。其他线程处理完毕后将结果转发回Platform Thread。长时间卡住Platform Thread应用有可能会被系统Watchdog强行杀死。&/p&&p&&br&&/p&&h2&UI Task Runner Thread(Dart Runner)&/h2&&p&&br&&/p&&p&UI Task Runner被Flutter Engine用于执行Dart root isolate代码(isolate我们后面会讲到,姑且先简单理解为Dart VM里面的线程)。Root isolate比较特殊,它绑定了不少Flutter需要的函数方法。Root isolate运行应用的main code。引擎启动的时候为其增加了必要的绑定,使其具备调度提交渲染帧的能力。对于每一帧,引擎要做的事情有:&br&- Root isolate通知Flutter Engine有帧需要渲染。&br&- Flutter Engine通知平台,需要在下一个vsync的时候得到通知。&br&- 平台等待下一个vsync&br&- 对创建的对象和Widgets进行Layout并生成一个Layer Tree,这个Tree马上被提交给Flutter Engine。当前阶段没有进行任何光栅化,这个步骤仅是生成了对需要绘制内容的描述。&br&- 创建或者更新Tree,这个Tree包含了用于屏幕上显示Widgets的语义信息。这个东西主要用于平台相关的辅助Accessibility元素的配置和渲染。&/p&&p&除了渲染相关逻辑之外Root Isolate还是处理来自Native Plugins的消息响应,Timers,Microtasks和异步IO。&br&我们看到Root Isolate负责创建管理的Layer Tree最终决定什么内容要绘制到屏幕上。因此这个线程的过载会直接导致卡顿掉帧。&br&如果确实有无法避免的繁重计算,建议将其放到独立的Isolate去执行,比如使用compute关键字或者放到非Root Isolate,这样可以避免应用UI卡顿。但是需要注意的是非Root Isolate缺少Flutter引擎需要的一些函数绑定,你无法在这个Isolate直接与Flutter Engine交互。所以只在需要大量计算的时候采用独立Isolate。&/p&&p&&br&&/p&&h2&GPU Task Runner&/h2&&p&&br&&/p&&p&GPU Task Runner被用于执行设备GPU的相关调用。UI Task Runner创建的Layer Tree信息是平台不相关,也就是说Layer Tree提供了绘制所需要的信息,具体如何实现绘制取决于具体平台和方式,可以是OpenGL,Vulkan,软件绘制或者其他Skia配置的绘图实现。GPU Task Runner中的模块负责将Layer Tree提供的信息转化为实际的GPU指令。GPU Task Runner同时也负责配置管理每一帧绘制所需要的GPU资源,这包括平台Framebuffer的创建,Surface生命周期管理,保证Texture和Buffers在绘制的时候是可用的。&/p&&p&基于Layer Tree的处理时长和GPU帧显示到屏幕的耗时,GPU Task Runner可能会延迟下一帧在UI Task Runner的调度。一般来说UI Runner和GPU Runner跑在不同的线程。存在这种可能,UI Runner在已经准备好了下一帧的情况下,GPU Runner却还正在向GPU提交上一帧。这种延迟调度机制确保不让UI Runner分配过多的任务给GPU Runner。&/p&&p&前面我们提到GPU Runner可以导致UI Runner的帧调度的延迟,GPU Runner的过载会导致Flutter应用的卡顿。一般来说用户没有机会向GPU Runner直接提交任务,因为平台和Dart代码都无法跑进GPU Runner。但是Embeder还是可以向GPU Runner提交任务的。因此建议为每一个Engine实例都新建一个专用的GPU Runner线程。&/p&&p&&br&&/p&&h2&IO Task Runner&/h2&&p&&br&&/p&&p&前面讨论的几个Runner对于执行任务的类型都有比较强的限制。Platform Runner过载可能导致系统WatchDog强杀,UI和GPU Runner过载则可能导致Flutter应用的卡顿。但是GPU线程有一些必要操作是比较耗时间的,比如IO,而这些操作正是IO Runner需要处理的。&/p&&p&IO Runner的主要功能是从图片存储(比如磁盘)中读取压缩的图片格式,将图片数据进行处理为GPU Runner的渲染做好准备。在Texture的准备过程中,IO Runner首先要读取压缩的图片二进制数据(比如PNG,JPEG),将其解压转换成GPU能够处理的格式然后将数据上传到GPU。这些复杂操作如果跑在GPU线程的话会导致Flutter应用UI卡顿。但是只有GPU Runner能够访问GPU,所以IO Runner模块在引擎启动的时候配置了一个特殊的Context,这个Context跟GPU Runner使用的Context在同一个ShareGroup。事实上图片数据的读取和解压是可以放到一个线程池里面去做的,但是这个Context的访问只能在特定线程才能保证安全。这也是为什么需要有一个专门的Runner来处理IO任务的原因。获取诸如&code&ui.Image&/code&这样的资源只有通过async call,当这个调用发生的时候Flutter Framework告诉IO Runner进行刚刚提到的那些图片异步操作。这样GPU Runner可以使用IO Runner准备好的图片数据而不用进行额外的操作。&/p&&p&用户操作,无论是Dart Code还是Native Plugins都是没有办法直接访问IO Runner。尽管Embeder可以将一些一般复杂任务调度到IO Runner,这不会直接导致Flutter应用卡顿,但是可能会导致图片和其它一些资源加载的延迟间接影响性能。所以建议为IO Runner创建一个专用的线程。&/p&&p&&br&&/p&&h2&各个平台目前默认Runner线程实现&/h2&&p&&br&&/p&&p&前面我们提到Engine Runner的线程可以按照实际情况进行配置,各个平台目前有自己的实现策略。&/p&&p&&br&&/p&&h2&iOS和Android&/h2&&p&&br&&/p&&blockquote&Mobile平台上面每一个Engine实例启动的时候会为UI,GPU,IO Runner各自创建一个新的线程。所有Engine实例共享同一个Platform Runner和线程。&/blockquote&&p&&br&&/p&&h2&Fuchsia&/h2&&p&&br&&/p&&blockquote&每一个Engine实例都为UI,GPU,IO,Platform Runner创建各自新的线程。&/blockquote&&p&&br&&/p&&h2&自定义配置线程可行方案&/h2&&p&&br&&/p&&p&我们注意到Mobile平台上面,Platform Runner和Thread是共享的。&br&引擎源码如下:&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-cpp&&&span&&/span&&span class=&n&&Shell&/span&&span class=&o&&::&/span&&span class=&n&&Shell&/span&&span class=&p&&(&/span&&span class=&n&&fxl&/span&&span class=&o&&::&/span&&span class=&n&&CommandLine&/span& &span class=&n&&command_line&/span&&span class=&p&&)&/span&
&span class=&o&&:&/span& &span class=&n&&command_line_&/span&&span class=&p&&(&/span&&span class=&n&&std&/span&&span class=&o&&::&/span&&span class=&n&&move&/span&&span class=&p&&(&/span&&span class=&n&&command_line&/span&&span class=&p&&))&/span& &span class=&p&&{&/span&
&span class=&n&&FXL_DCHECK&/span&&span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&n&&g_shell&/span&&span class=&p&&);&/span&
&span class=&n&&gpu_thread_&/span&&span class=&p&&.&/span&&span class=&n&&reset&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&Thread&/span&&span class=&p&&(&/span&&span class=&s&&&gpu_thread&&/span&&span class=&p&&));&/span&
&span class=&n&&ui_thread_&/span&&span class=&p&&.&/span&&span class=&n&&reset&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&Thread&/span&&span class=&p&&(&/span&&span class=&s&&&ui_thread&&/span&&span class=&p&&));&/span&
&span class=&n&&io_thread_&/span&&span class=&p&&.&/span&&span class=&n&&reset&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&Thread&/span&&span class=&p&&(&/span&&span class=&s&&&io_thread&&/span&&span class=&p&&));&/span&
&span class=&c1&&// Since we are not using fml::Thread, we need to initialize the message loop&/span&
&span class=&c1&&// manually.&/span&
&span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&MessageLoop&/span&&span class=&o&&::&/span&&span class=&n&&EnsureInitializedForCurrentThread&/span&&span class=&p&&();&/span&
&span class=&n&&blink&/span&&span class=&o&&::&/span&&span class=&n&&Threads&/span& &span class=&n&&threads&/span&&span class=&p&&(&/span&&span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&MessageLoop&/span&&span class=&o&&::&/span&&span class=&n&&GetCurrent&/span&&span class=&p&&().&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&(),&/span&
&span class=&n&&gpu_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&(),&/span&
&span class=&n&&ui_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&(),&/span&
&span class=&n&&io_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&());&/span&
&span class=&n&&blink&/span&&span class=&o&&::&/span&&span class=&n&&Threads&/span&&span class=&o&&::&/span&&span class=&n&&Set&/span&&span class=&p&&(&/span&&span class=&n&&threads&/span&&span class=&p&&);&/span&
&span class=&n&&blink&/span&&span class=&o&&::&/span&&span class=&n&&Threads&/span&&span class=&o&&::&/span&&span class=&n&&Gpu&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&PostTask&/span&&span class=&p&&([&/span&&span class=&k&&this&/span&&span class=&p&&]()&/span& &span class=&p&&{&/span& &span class=&n&&InitGpuThread&/span&&span class=&p&&();&/span& &span class=&p&&});&/span&
&span class=&n&&blink&/span&&span class=&o&&::&/span&&span class=&n&&Threads&/span&&span class=&o&&::&/span&&span class=&n&&UI&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&PostTask&/span&&span class=&p&&([&/span&&span class=&k&&this&/span&&span class=&p&&]()&/span& &span class=&p&&{&/span& &span class=&n&&InitUIThread&/span&&span class=&p&&();&/span& &span class=&p&&});&/span&
&span class=&n&&blink&/span&&span class=&o&&::&/span&&span class=&n&&SetRegisterNativeServiceProtocolExtensionHook&/span&&span class=&p&&(&/span&
&span class=&n&&PlatformViewServiceProtocol&/span&&span class=&o&&::&/span&&span class=&n&&RegisterHook&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&&br&&/p&&p&&br&&/p&&p&这里我们可以进行改动,让引擎每个实例初始化独自的线程:&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-cpp&&&span&&/span&
&span class=&n&&gpu_thread_&/span&&span class=&p&&.&/span&&span class=&n&&reset&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&Thread&/span&&span class=&p&&(&/span&&span class=&s&&&gpu_thread&&/span&&span class=&p&&));&/span&
&span class=&n&&ui_thread_&/span&&span class=&p&&.&/span&&span class=&n&&reset&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&Thread&/span&&span class=&p&&(&/span&&span class=&s&&&ui_thread&&/span&&span class=&p&&));&/span&
&span class=&n&&io_thread_&/span&&span class=&p&&.&/span&&span class=&n&&reset&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&Thread&/span&&span class=&p&&(&/span&&span class=&s&&&io_thread&&/span&&span class=&p&&));&/span&
&span class=&n&&platform_thread_&/span&&span class=&p&&.&/span&&span class=&n&&reset&/span&&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&n&&fml&/span&&span class=&o&&::&/span&&span class=&n&&Thread&/span&&span class=&p&&(&/span&&span class=&s&&&platform_thread&&/span&&span class=&p&&));&/span&
&span class=&n&&blink&/span&&span class=&o&&::&/span&&span class=&n&&Threads&/span& &span class=&n&&threads&/span&&span class=&p&&(&/span&&span class=&n&&platform_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&(),&/span&
&span class=&n&&gpu_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&(),&/span&
&span class=&n&&ui_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&(),&/span&
&span class=&n&&io_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&GetTaskRunner&/span&&span class=&p&&());&/span&
&/code&&/pre&&/div&&p&&br&&/p&&p&&br&&/p&&p&理论上你可以配置任意线程供其使用,不过最好遵循最佳实践。&/p&&p&&br&&/p&&h2&代码导读&/h2&&p&&br&&/p&&p&iOS Android平台可以参考Flutter Engine源码:&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-bash&&&span&&/span&flutter/common/threads.cc
flutter/shell/common/shell.cc
&/code&&/pre&&/div&&p&&br&&/p&&p&&br&&/p&&h2& Dart isolate机制&/h2&&p&&br&&/p&&blockquote&An isolated Dart execution context. 这是文档对isolate的定义。&/blockquote&&p&&br&&/p&&h2&isolate定义&/h2&&p&&br&&/p&&p&isolate是Dart对actor并发模式的实现。运行中的Dart程序由一个或多个actor组成,这些actor也就是Dart概念里面的isolate。isolate是有自己的内存和单线程控制的运行实体。isolate本身的意思是“隔离”,因为isolate之间的内存在逻辑上是隔离的。isolate中的代码是按顺序执行的,任何Dart程序的并发都是运行多个isolate的结果。因为Dart没有共享内存的并发,没有竞争的可能性所以不需要锁,也就不用担心死锁的问题。&/p&&p&&br&&/p&&h2&isolate之间的通信&/h2&&p&&br&&/p&&p&由于isolate之间没有共享内存,所以他们之间的通信唯一方式只能是通过Port进行,而且Dart中的消息传递总是异步的。&/p&&p&&br&&/p&&h2&isolate与普通线程的区别&/h2&&p&&br&&/p&&p&我们可以看到isolate神似Thread,但实际上两者有本质的区别。操作系统内内的线程之间是可以有共享内存的而isolate没有,这是最为关键的区别。&/p&&p&&br&&/p&&h2&isolate实现简述&/h2&&p&&br&&/p&&p&我们可以阅读Dart源码里面的&a href=&http://link.zhihu.com/?target=http%3A//isolate.cc& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&isolate.cc&/span&&span class=&invisible&&&/span&&/a&文件看看isolate的具体实现。&br&我们可以看到在isolate创建的时候有以下几个主要步骤:&br&- 初始化isolate数据结构&br&- 初始化堆内存(Heap)&br&- 进入新创建的isolate,使用跟isolate一对一的线程运行isolate&br&- 配置Port&br&- 配置消息处理机制(Message Handler)&br&- 配置Debugger,如果有必要的话&br&- 将isolate注册到全局监控器(Monitor)&/p&&p&我们看看isolate开始运行的主要代码&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-cpp&&&span&&/span&&span class=&n&&Thread&/span&&span class=&o&&*&/span& &span class=&n&&Isolate&/span&&span class=&o&&::&/span&&span class=&n&&ScheduleThread&/span&&span class=&p&&(&/span&&span class=&kt&&bool&/span& &span class=&n&&is_mutator&/span&&span class=&p&&,&/span& &span class=&kt&&bool&/span& &span class=&n&&bypass_safepoint&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// Schedule the thread into the isolate by associating&/span&
&span class=&c1&&// a 'Thread' structure with it (this is done while we are holding&/span&
&span class=&c1&&// the thread registry lock).&/span&
&span class=&n&&Thread&/span&&span class=&o&&*&/span& &span class=&kr&&thread&/span& &span class=&o&&=&/span& &span class=&nb&&NULL&/span&&span class=&p&&;&/span&
&span class=&n&&OSThread&/span&&span class=&o&&*&/span& &span class=&n&&os_thread&/span& &span class=&o&&=&/span& &span class=&n&&OSThread&/span&&span class=&o&&::&/span&&span class=&n&&Current&/span&&span class=&p&&();&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&os_thread&/span& &span class=&o&&!=&/span& &span class=&nb&&NULL&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&n&&MonitorLocker&/span& &span class=&n&&ml&/span&&span class=&p&&(&/span&&span class=&n&&threads_lock&/span&&span class=&p&&(),&/span& &span class=&nb&&false&/span&&span class=&p&&);&/span&
&span class=&c1&&// Check to make sure we don't already have a mutator thread.&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&is_mutator&/span& &span class=&o&&&&&/span& &span class=&n&&scheduled_mutator_thread_&/span& &span class=&o&&!=&/span& &span class=&nb&&NULL&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nb&&NULL&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&while&/span& &span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&n&&bypass_safepoint&/span& &span class=&o&&&&&/span& &span class=&n&&safepoint_handler&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&SafepointInProgress&/span&&span class=&p&&())&/span& &span class=&p&&{&/span&
&span class=&n&&ml&/span&&span class=&p&&.&/span&&span class=&n&&Wait&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&c1&&// Now get a free Thread structure.&/span&
&span class=&kr&&thread&/span& &span class=&o&&=&/span& &span class=&n&&thread_registry&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&GetFreeThreadLocked&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&n&&is_mutator&/span&&span class=&p&&);&/span&
&span class=&n&&ASSERT&/span&&span class=&p&&(&/span&&span class=&kr&&thread&/span& &span class=&o&&!=&/span& &span class=&nb&&NULL&/span&&span class=&p&&);&/span&
&span class=&c1&&// Set up other values and set the TLS value.&/span&
&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&isolate_&/span& &span class=&o&&=&/span& &span class=&k&&this&/span&&span class=&p&&;&/span&
&span class=&n&&ASSERT&/span&&span class=&p&&(&/span&&span class=&n&&heap&/span&&span class=&p&&()&/span& &span class=&o&&!=&/span& &span class=&nb&&NULL&/span&&span class=&p&&);&/span&
&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&heap_&/span& &span class=&o&&=&/span& &span class=&n&&heap&/span&&span class=&p&&();&/span&
&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&set_os_thread&/span&&span class=&p&&(&/span&&span class=&n&&os_thread&/span&&span class=&p&&);&/span&
&span class=&n&&ASSERT&/span&&span class=&p&&(&/span&&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&execution_state&/span&&span class=&p&&()&/span& &span class=&o&&==&/span& &span class=&n&&Thread&/span&&span class=&o&&::&/span&&span class=&n&&kThreadInNative&/span&&span class=&p&&);&/span&
&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&set_execution_state&/span&&span class=&p&&(&/span&&span class=&n&&Thread&/span&&span class=&o&&::&/span&&span class=&n&&kThreadInVM&/span&&span class=&p&&);&/span&
&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&set_safepoint_state&/span&&span class=&p&&(&/span&&span class=&mi&&0&/span&&span class=&p&&);&/span&
&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&set_vm_tag&/span&&span class=&p&&(&/span&&span class=&n&&VMTag&/span&&span class=&o&&::&/span&&span class=&n&&kVMTagId&/span&&span class=&p&&);&/span&
&span class=&n&&ASSERT&/span&&span class=&p&&(&/span&&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&no_safepoint_scope_depth&/span&&span class=&p&&()&/span& &span class=&o&&==&/span& &span class=&mi&&0&/span&&span class=&p&&);&/span&
&span class=&n&&os_thread&/span&&span class=&o&&-&&/span&&span class=&n&&set_thread&/span&&span class=&p&&(&/span&&span class=&kr&&thread&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&is_mutator&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&n&&scheduled_mutator_thread_&/span& &span class=&o&&=&/span& &span class=&kr&&thread&/span&&span class=&p&&;&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&k&&this&/span& &span class=&o&&!=&/span& &span class=&n&&Dart&/span&&span class=&o&&::&/span&&span class=&n&&vm_isolate&/span&&span class=&p&&())&/span& &span class=&p&&{&/span&
&span class=&n&&scheduled_mutator_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&set_top&/span&&span class=&p&&(&/span&&span class=&n&&heap&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&new_space&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&top&/span&&span class=&p&&());&/span&
&span class=&n&&scheduled_mutator_thread_&/span&&span class=&o&&-&&/span&&span class=&n&&set_end&/span&&span class=&p&&(&/span&&span class=&n&&heap&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&new_space&/span&&span class=&p&&()&/span&&span class=&o&&-&&/span&&span class=&n&&end&/span&&span class=&p&&());&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&n&&Thread&/span&&span class=&o&&::&/span&&span class=&n&&SetCurrent&/span&&span class=&p&&(&/span&&span class=&kr&&thread&/span&&span class=&p&&);&/span&
&span class=&n&&os_thread&/span&&span class=&o&&-&&/span&&span class=&n&&EnableThreadInterrupts&/span&&span class=&p&&();&/span&
&span class=&kr&&thread&/span&&span class=&o&&-&&/span&&span class=&n&&ResetHighWatermark&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&kr&&thread&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&&br&&/p&&p&&br&&/p&&p&我们可以看到Dart本身抽象了isolate和thread,实际上底层还是使用操作系统的提供的OSThread。&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-db8a18e3dc96a6a6ec48a31c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&627& data-rawheight=&297& class=&origin_image zh-lightbox-thumb& width=&627& data-original=&https://pic1.zhimg.com/v2-db8a18e3dc96a6a6ec48a31c_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&h2&Flutter Engine Runners与Dart Isolate&/h2&&p&&br&&/p&&p&有朋友看到这里可能会问既然Flutter Engine有自己的Runner,那为何还要Dart的Isolate呢,他们之间又是什么关系呢?&/p&&p&那我们还要从Runner具体的实现说起,Runner是一个抽象概念,我们可以往Runner里面提交任务,任务被Runner放到它所在的线程去执行,这跟iOS GCD的执行队列很像。我们查看iOS Runner的实现实际上里面是一个loop,这个loop就是&a href=&http://link.zhihu.com/?target=https%3A//developer.apple.com/documentation/corefoundation/cfrunloop-rht& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&CFRunloop&/a&,在iOS平台上Runner具体实现就是CFRunloop。被提交的任务被放到CFRunloop去执行。&/p&&p&Dart的Isolate是Dart虚拟机自己管理的,Flutter Engine无法直接访问。Root Isolate通过Dart的C++调用能力把UI渲染相关的任务提交到UI Runner执行这样就可以跟Flutter Engine相关模块进行交互,Flutter UI相关的任务也被提交到UI Runner也可以相应的给Isolate一些事件通知,UI Runner同时也处理来自App方面Native Plugin的任务。&/p&&p&所以简单来说Dart isolate跟Flutter Runner是相互独立的,他们通过任务调度机制相互协作。&/p&&p&&br&&/p&&h2&踩坑血泪史&/h2&&p&&br&&/p&&p&理解Flutter Engine的原理以及Dart虚拟机的异步实现,让我们避免采坑,更加灵活高效地进行开发。&br&在项目应用过程我们踩过不少坑,在采坑和填坑的过程中不断学习。这里我简单聊其中一个具体的案例:当时我们需要把Native加载好图片数据注册到Engine里面去以便生成Texture渲染,使用完资源我们需要将其移除,看起来非常清晰的逻辑竟然造成了野指针问题。后来排查到注册的时候在一个子线程进行而移除却在Platform线程进行,在弄清楚线程结构以后问题也就迎刃而解。&/p&&p&&br&&/p&&h2&结语&/h2&&p&&br&&/p&&p&本文我们主要讨论了Flutter引擎层面的线程配置管理以及Dart本身isolate的机制。在深入了解Flutter线程机制以后,我们在开发过程当中能够更加得心应手。在理解Flutter设计的过程中,我们得到启发如何去设计类似应用内的线程结构。&/p&&p&&br&&/p&&h2&延展讨论&/h2&&p&&br&&/p&&p&目前团队将Flutter集成到现有的App是以单例的方式启动的,这样避免了Native与Flutter页面切换过程当中由于Flutter冷启动导致的耗时问题。但是单引擎模式启动在支持多个Flutter页面的时候逻辑变得复杂。最为理想的状态,我们希望每一个页面都是一个相对独立的组件,这可能需要引擎层面进行一些改造。一种可能设想是一个组件对应一个引擎实例,多实例的引擎在线程模式方面面临一些挑战。包括线程复用,线程间的通信,线程性能调优,引擎间的协作的问题。&/p&&p&我们将在这方面继续深入的探索和尝试,请后续关注我们公众号发布的文章。另外,闲鱼期待你的加入!&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//weixin.qq.com/r/Pi4nIyXEpO3YKWFAb3u6& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&weixin.qq.com/r/Pi4nIyX&/span&&span class=&invisible&&EpO3YKWFAb3u6&/span&&span class=&ellipsis&&&/span&&/a& (二维码自动识别)&/p&&h2&参考资料&/h2&&p&&br&&/p&&p&&br&&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//github.com/flutter/flutter& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Flutter 开发文档&/a&&/li&&/ul&&p&&br&&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//github.com/flutter/engine& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Flutter 引擎文档&/a&&/li&&/ul&&p&&br&&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//flutter.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Flutter IO&/a&&/li&&/ul&&p&&br&&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.dartlang.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Dart 语言开发文档&/a&&/li&&/ul&&p&&br&&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//book.douban.com/subject//& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《Dart编程语言》&/a&&/li&&/ul&&p&&/p&
作者:闲鱼技术福居 在终端业务需求日益复杂,版本迭代日趋于频繁的情况下,我们迫切需要优秀的多端统一跨平台开发方案以提升研发效率。目前已有类似RN,Weex这种通过JavaScript桥接到Native的终端技术方案。但是,基于JavaScript的桥接模式有JavaScriptCor…
&blockquote&&b&E3 2018,任天堂的直面会还是那么与众不同。&/b&&/blockquote&&hr&&p&在直面会开始30分钟前,就已经有8万粉丝以每分钟+10000人的增势守候在Youtube的英语直播间入口,用每秒数十条信息快到看不清的刷新速度表达着他们的紧张、兴奋、还有希望。&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-0d4e2efe99f5f61c68f01b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&550& data-rawheight=&362& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-0d4e2efe99f5f61c68f01b_r.jpg&&&/figure&&p&小编试图发出一条“任地狱快点给我银河战士Prime4”的信息,瞬间就被淹没在各国语言组成的疯狂聊天记录与颜文字的海洋中。但遗憾的是,任天堂似乎完全遗忘了它在E3 2017的画饼,令人牵挂的Prime4直到最后也没有现身。&/p&&p&精彩,基本聚焦在最初的10分钟里,任天堂如连珠炮般抛出了数款新作、DLC、以及先前兑现的画饼。&/p&&h2&&b&《Daemon x Machina》——超高速机甲战斗&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/183552& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic4.zhimg.com/80/v2-c2b32ed1d859f63ebd9ebf3_b.jpg& data-lens-id=&183552&&
&img class=&thumbnail& src=&https://pic4.zhimg.com/80/v2-c2b32ed1d859f63ebd9ebf3_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/183552&/span&
&/a&&p&打头阵的很意外是一款任天堂甚少涉及的机甲战斗游戏《Daemon x Machina》。它由Marvelous负责开发,&b&此前FS社《装甲核心》的主创成员佃謙一郎参与制作,机甲设计为《超时空要塞》系列的河森正治&/b&,因此可以看到很多眼熟的硬核机甲设计,同时画面也变为更适合NS表现的2D动画渲染风格。&/p&&p&在FS社逐渐放弃《装甲核心》的现在,在NS上能玩到这样的精神续作无疑是令机甲迷们额手称幸的一件事。本作2019年内发售。&/p&&h2&&b&《异度之刃2前传:黄金之国》——能再玩100小时的资料片?&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/844096& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic4.zhimg.com/80/v2-937fbd01af7c02c4fe45be379a79a003_b.jpg& data-lens-id=&844096&&
&img class=&thumbnail& src=&https://pic4.zhimg.com/80/v2-937fbd01af7c02c4fe45be379a79a003_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/844096&/span&
&/a&&p&&b&全新的主角,全新的异刃,全新的故事。&/b&从视频看来,《异度之刃2》的首个DLC资料片《黄金之国伊拉》比我们想象的要厚道太多——之前购买过季票的玩家,一定会觉得物超所值。&/p&&p&这个篇章讲述500年前光与灭的圣杯之战,主角也换成了上一任“最强异刃”的主人,故事无疑令人期待,而本篇出色的庞大地图也得到了物尽其用。&b&本DLC将于今年9月4日发售&/b&,届时还会发售包含本篇+DLC的“完全版”。具体新要素细节,请留意我们的后续报道。&/p&&h2&&b&《宝可梦Let's go:皮卡丘/伊布》——精灵球在大猩猩手里显得好小&/b&&/h2&&figure&&img src=&https://pic3.zhimg.com/50/v2-72a04adb7a38ebe9844f41_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&550& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-72a04adb7a38ebe9844f41_r.jpg&&&/figure&&p&此前已被披露过的NS重磅级作品,但不少玩家认为任天堂用这款游戏作为E3发布会的压轴戏码效果更好。&/p&&p&大猩猩雷吉亲自为我们展示了任天堂小巧可爱的精灵球,以及很任氏的捆绑商法——买精灵球,送你个梦幻宝可梦。&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-4fc9d2e2b4d25b24f523f1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&550& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-4fc9d2e2b4d25b24f523f1_r.jpg&&&/figure&&h2&&b&《超级马里奥聚会》——没朋友就不要买了&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/905536& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic3.zhimg.com/80/v2-e357a11b67197ebbecf093e_b.jpg& data-lens-id=&905536&&
&img class=&thumbnail& src=&https://pic3.zhimg.com/80/v2-e357a11b67197ebbecf093e_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/905536&/span&
&/a&&p&任天堂例牌菜的聚会小游戏合集,但是视频中通过数个NS屏幕摆放串联,拼接成一体的游戏方式确实让人耳目一新。尽管游戏本身吸引力有限,但任天堂再次表现出强大的广告制作能力,忍不住让人跃跃欲试。&b&《超级马里奥聚会》日发售&/b&。&/p&&h2&&b&《火焰之纹章:风花雪月》——有些变样的全新火纹&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/520448& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic1.zhimg.com/80/v2-aa4df483515cfc88445b44_b.jpg& data-lens-id=&520448&&
&img class=&thumbnail& src=&https://pic1.zhimg.com/80/v2-aa4df483515cfc88445b44_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/520448&/span&
&/a&&p&这大概是迄今为止2D动画渲染效果最棒的《火焰纹章》——等等,这效果貌似十分眼熟,是不是有些《XX无双》的感觉哦?&/p&&p&大地图-战斗画面无缝式切换;作战单位身边的士兵令人想起了《梦幻模拟战》的设计;什么?主角还能像RPG那样在城池和村庄中自由散步?这些要素叠加起来,让这款游戏看起来似乎没那么像传统火纹了。&/p&&p&&b&但经验告诉我们任天堂并不会无谓的做出华而不实的游戏设计&/b&,这些崭新元素对游戏的影响,就让我们拭目以待。本作将于2019年春季与大家见面。&/p&&h2&&b&《堡垒之夜》——免费下载,内购氪金&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/755136& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic1.zhimg.com/80/v2-7ed19ca6f4d2f5f2da602f002d9f3270_b.jpg& data-lens-id=&755136&&
&img class=&thumbnail& src=&https://pic1.zhimg.com/80/v2-7ed19ca6f4d2f5f2da602f002d9f3270_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/755136&/span&
&/a&&p&脱胎于《绝地求生》的理念,却拥有着前者以上的游戏性,而且没有了写实杀戮的血腥表现,《堡垒之夜》显然非常适合面向全年龄的任天堂平台。&b&本作将于6月13日(就是今天)上架E-shop&/b&,并且和其他平台一样免费下载,采用内购模式。&/p&&h2&&b&《煮糊了2》&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/148352& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic4.zhimg.com/80/v2-ae2d6b5afed144afba3bc11bb2f1062b_b.jpg& data-lens-id=&148352&&
&img class=&thumbnail& src=&https://pic4.zhimg.com/80/v2-ae2d6b5afed144afba3bc11bb2f1062b_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/148352&/span&
&/a&&p&著名互相伤害游戏《煮糊了2》将于&b&8月7日&/b&登陆包括NS在内的所有主流游戏平台。游戏将加入大量的新地图与新要素,线下4人联机模式可以体现NS独有的乐趣。&/p&&h2&&b&《空洞骑士》&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/174848& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic2.zhimg.com/80/v2-d3fc630e3a084e7b3666db6fbad88995_b.jpg& data-lens-id=&174848&&
&img class=&thumbnail& src=&https://pic2.zhimg.com/80/v2-d3fc630e3a084e7b3666db6fbad88995_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/174848&/span&
&/a&&p&经历过一次莫名其妙的延期,Switch版《空洞骑士》总算在&b&6月13日(就是今天)上架E-shop&/b&,NS版是包含了此前的所有DLC内容的“完全版”。只是来得太晚,喜欢“银河城”的玩友大概早已玩腻了吧。&/p&&h2&&b&《八方旅人》开放试玩&/b&&/h2&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/230976& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic1.zhimg.com/80/v2-1b06c64bdddec9b1a9d6b8_b.jpg& data-lens-id=&230976&&
&img class=&thumbnail& src=&https://pic1.zhimg.com/80/v2-1b06c64bdddec9b1a9d6b8_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/230976&/span&
&/a&&p&预定于日发售的《八方旅人》将于&b&明天(6月14日)在E-shop开放下载第二个试玩版&/b&,并且试玩存档允许被继承到正式版中。至于内容与上一个试玩版有何不同暂且未知。&/p&&p&在其后的游戏串烧中,任天堂一口气公布了数十个囊括第三方游戏在内的登陆计划——虽然大部分都是移植或冷饭,&b&但它们大多数都有具体或大致的发售日期,没有画饼。&/b&&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-7c6e6aece46f298d49c05d_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic2.zhimg.com/50/v2-7c6e6aece46f298d49c05d_r.jpg&&&figcaption&《喷射乌贼娘2》“章鱼”资料片——2018年夏发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-ad272a3d44e1abc2f1ba37_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&323& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-ad272a3d44e1abc2f1ba37_r.jpg&&&figcaption&《我的世界NS版》——6月21日发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-01eb8a9e311a199f9edde_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&304& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-01eb8a9e311a199f9edde_r.jpg&&&figcaption&《马里奥网球ACE》——6月22日发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-c2c8c2d9e3bb_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-c2c8c2d9e3bb_r.jpg&&&figcaption&《马里奥+疯兔王国之战:大金刚冒险篇》——6月26日发售&/figcaption&&/figure&&figure&&img src=&https://pic1.zhimg.com/50/v2-fb68453eddb5eb45cbfee5c091bf964e_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&321& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-fb68453eddb5eb45cbfee5c091bf964e_r.jpg&&&figcaption&《古惑狼 疯狂三部曲》——6月29日发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-ab813cd36faece8aaae2f7_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&307& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-ab813cd36faece8aaae2f7_r.jpg&&&figcaption&《德军总部2》——6月29日发售&/figcaption&&/figure&&figure&&img src=&https://pic4.zhimg.com/50/v2-cb989feb8a73fc7eea63120_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic4.zhimg.com/50/v2-cb989feb8a73fc7eea63120_r.jpg&&&figcaption&《蘑菇队长》——7月13日发售&/figcaption&&/figure&&figure&&img src=&https://pic1.zhimg.com/50/v2-f513b9de6f677d33680f_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&308& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-f513b9de6f677d33680f_r.jpg&&&figcaption&《王者荣耀》国际版——2018年秋季发售&/figcaption&&/figure&&figure&&img src=&https://pic1.zhimg.com/50/v2-dcd5b7aba749_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&347& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-dcd5b7aba749_r.jpg&&&figcaption&《STARLINK:阿特拉斯之战》——10月6日发售&/figcaption&&/figure&&figure&&img src=&https://pic1.zhimg.com/50/v2-5a2b6b338d5dde6b3dffbaed5baaee2d_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&309& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-5a2b6b338d5dde6b3dffbaed5baaee2d_r.jpg&&&figcaption&《舞力全开2019》——10月23日发售&/figcaption&&/figure&&p&《龙珠斗士Z》——2018年内发售&/p&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/856896& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic3.zhimg.com/80/v2-934b5a682c250a_b.jpg& data-lens-id=&856896&&
&img class=&thumbnail& src=&https://pic3.zhimg.com/80/v2-934b5a682c250a_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/856896&/span&
&/a&&p&《SNK女杰乱斗》——日&/p&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/549120& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic4.zhimg.com/80/v2-99e1cabe57afdfa7e56f_b.jpg& data-lens-id=&549120&&
&img class=&thumbnail& src=&https://pic4.zhimg.com/80/v2-99e1cabe57afdfa7e56f_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/549120&/span&
&/a&&figure&&img src=&https://pic2.zhimg.com/50/v2-598de2d95e576dd374da576_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&307& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic2.zhimg.com/50/v2-598de2d95e576dd374da576_r.jpg&&&figcaption&《像素方舟》——2018年秋季发售&/figcaption&&/figure&&figure&&img src=&https://pic4.zhimg.com/50/v2-47dd790537def26ebdc4dfaf5e748ceb_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&311& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic4.zhimg.com/50/v2-47dd790537def26ebdc4dfaf5e748ceb_r.jpg&&&figcaption&《Ninjala》——2019年春季发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-ec3969de03fbc6b9c316_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&312& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-ec3969de03fbc6b9c316_r.jpg&&&figcaption&《卡尔卡松》——2018年假期发售&/figcaption&&/figure&&figure&&img src=&https://pic1.zhimg.com/50/v2-424aefb28b45_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&311& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-424aefb28b45_r.jpg&&&figcaption&《FIFA 19》——9月28日发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-bb96d51f70b_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&313& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-bb96d51f70b_r.jpg&&&figcaption&《方舟 生存进化》2018年秋季&/figcaption&&/figure&&figure&&img src=&https://pic1.zhimg.com/50/v2-68ab809ea6f1e8c799a03d8df307e23c_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&278& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-68ab809ea6f1e8c799a03d8df307e23c_r.jpg&&&figcaption&《废土2:导演剪辑版》——2018年秋季&/figcaption&&/figure&&figure&&img src=&https://pic4.zhimg.com/50/v2-2ccd60da8b3c9a55e6d120e88c2058cd_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&315& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic4.zhimg.com/50/v2-2ccd60da8b3c9a55e6d120e88c2058cd_r.jpg&&&figcaption&《帕拉丁》——已发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-fb871bcdbdeff_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&308& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-fb871bcdbdeff_r.jpg&&&figcaption&《辐射:避难所》——已发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-8c4b52d4c14e7df6b6bfb279e7fde48f_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&370& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-8c4b52d4c14e7df6b6bfb279e7fde48f_r.jpg&&&figcaption&《黑暗之魂重制版》——2018年夏季&/figcaption&&/figure&&figure&&img src=&https://pic2.zhimg.com/50/v2-00ca79eba76ed39fbee23e_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&313& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic2.zhimg.com/50/v2-00ca79eba76ed39fbee23e_r.jpg&&&figcaption&《美好世界》——2018年秋季发售&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-de565d33fbae7b6846aaa066daba64ba_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&322& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-de565d33fbae7b6846aaa066daba64ba_r.jpg&&&figcaption&《洛克人11》——10月2日发售&/figcaption&&/figure&&figure&&img src=&https://pic4.zhimg.com/50/v2-1fc925eb6eec4bfa0fa2_b.jpg& data-size=&normal& data-rawwidth=&550& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic4.zhimg.com/50/v2-1fc925eb6eec4bfa0fa2_r.jpg&&&figcaption&《超回转寿司先锋》——已发售&/figcaption&&/figure&&h2&&b&《任天堂大乱斗:终极版》&/b&&/h2&&p&自樱井政博登场之后,《任天堂大乱斗:终极版》占据了整个直面会剩下的60%的时间(算上最后的嘉宾时间,可能达到了骇人的90%…)。&/p&&p&从演示的海量新角色新关卡不难看出这是最丰盛最豪华,无愧于终极之名的《任天堂大乱斗》。诸如马里奥、林克等角色都与时俱进地加入了《奥德赛》与《荒野之息》的形象和技能,贝姐、RYU、吃豆人、索尼克等第三方明星角色也纷纷加盟。紧随这款游戏而来的,还有吓死人的海量Amiibo。&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-cbd85ffb3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&550& data-rawheight=&264& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic4.zhimg.com/50/v2-cbd85ffb3_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/50/v2-e5b0a37fd89_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&550& data-rawheight=&264& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic3.zhimg.com/50/v2-e5b0a37fd89_r.jpg&&&/figure&&p&樱井制作人不厌其烦地对这款终极大乱斗每个人物的特色、玩法、关卡、技能、彩蛋、对战模式进行了非常非常详尽且漫长的解说……&/p&&p&在这之后,樱井先生又与三位现场嘉宾展开更加热情洋溢的讨论。在这个视频延续了25分钟之后,直播间不断下跌的观众人数告诉我这场直面会大概已经结束了。&/p&&p&&b&如果你是任天堂的铁杆粉丝,那么这款游戏中蕴含的无数情怀彩蛋无疑是让你欲仙欲死的盛宴,&/b&《任天堂大乱斗:终极版》将于&b&日&/b&准时发售。&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-5a502a15aa0e3a512d022a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&550& data-rawheight=&303& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-5a502a15aa0e3a512d022a_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/50/v2-ebe31d6c0c77bb9d0896_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&550& data-rawheight=&308& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic1.zhimg.com/50/v2-ebe31d6c0c77bb9d0896_r.jpg&&&/figure&&h2&&b&总结&/b&&/h2&&p&总的来说,四大重量级独占,火纹新作,大乱斗新作,加上数十款第三方移植作品,其实任天堂NS今年可以玩的东西并不少。&b&发布会上公布的所有游戏,基本都是已确定发售时期的干货。&/b&&/p&&p&问题当然也显而易见,发布会前1/3的节奏非常棒,但《任天堂大乱斗终极版》的比例设置失调是多数玩家对本次直面会最大的槽点。假如能

我要回帖

更多关于 thread类的方法有哪些 的文章

 

随机推荐