pc的刺客信条起源1.05修改版本怎么设置中文啊,因为点开Options没有Language 的选项啊

&>&&>&&>&正文
《刺客信条中国》中文设置教程 怎么设置中文
10:54:52 来源:游民星空[原创] 作者:Shy夏夏 编辑:Shy夏夏 
  《刺客信条编年史:中国》一开始界面是默认的英文,但是游戏是自带中文的,很多英语不太好的玩家不知道如何设置,下面小编就为大家带来刺客信条中国的中文设置教程,教大家怎么设置中文。
《刺客信条:编年史》精华文章推荐
  点击MENU进入菜单
点击HELP&OPTIONS
点击SETTING
在Language中选择繁体中文即可
  修改成功截图
更多相关内容请关注:
用手机访问
扫一扫,手机浏览
没有任何记录
没有任何记录
游戏制作:Climax、育碧蒙特利尔
游戏发行:育碧
游戏平台:PC/XboxOne/PS4/PS Vita
上市时间:
《刺客信条:编年史》三部曲已经发售了中国部分,现在官方正式公开了完整三部曲的游戏预告,我们将会看到少芸再度上场,以及来自印度的刺客大师阿尔巴兹·米尔,和来自俄罗斯的铁血刺客尼古拉·奥列洛夫。
《AC编年史:中国》公布发售预告,主角为女刺客邵云,《AC大革命》季票可免费,单独售价10美元
《刺客信条:编年史之中国》日前发布演示,中国明朝刺客Shao Jun打击邪恶,重塑刺客兄弟会。
没有任何记录
单机游戏下载
综合热点资讯&figure&&img src=&https://pic1.zhimg.com/v2-3ad2b89fdeeb151_b.jpg& data-rawwidth=&900& data-rawheight=&718& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic1.zhimg.com/v2-3ad2b89fdeeb151_r.jpg&&&/figure&&p&从 2014 年第一篇公众号文章开始,三年多时间我竟然已经写下了 386 篇文章,涵盖技术,管理,创业和一些莫名其妙的感悟。这便是小小的坚持迸发出的能量:不经意间,&b&日拱一卒的零零碎碎&/b&汇集出这般美妙的结果。&/p&&p&我常说:读自己的日记,仿佛在跟过去的自己对话。读自己的文章也是如此。早上在 4S 店保养小车,闲来翻翻自己的文字,感觉很棒 —— 这并不是说我觉得我的文字有多棒,而是文字中透出的我的想法,成熟的不成熟的,都承载着我的成长。有这些文字(以及少量日记)作伴,我的 2017 虽不完美,好些计划也没完成,但起码留下了些什么。&/p&&p&2017 年我的第一篇文章 &a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Daee8fa02ebd0d9b6d289%26chksm%3D8704aaf3bb29ed954aff792917daea06e1619afc0de392c6eefd206%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Policy Engine 的前世今生&/a& 就振聋发聩 —— 火车上的一次突发奇想加上接下来三天的各种实验,奠定了 Tubi TV 这一年诸多工作的基石,也埋下了一些神坑让 team,甚至 elixir 1.7 去填(比如这个:&a href=&http://link.zhihu.com/?target=https%3A//github.com/elixir-lang/elixir/issues/7047& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/elixir-lang/&/span&&span class=&invisible&&elixir/issues/7047&/span&&span class=&ellipsis&&&/span&&/a&)。现在我们线上奔跑的代码已经和文中描述的大大不同,单 policy 一次编译时间也从 10 分钟,优化到几秒钟,但其中的思路,还是值得大家一看,甚至,文中提到的 &a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3Didx%3D1%26sn%3D9cc0fadcdbab12%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何愉快地撰写 Parser&/a&,也值得大家重读。&/p&&p&elixir 是我在 2015 年就在跟进的语言,但一路来都是写写小的 side project,直到 2017 年,在 Policy Engine 尝到甜头后,才正式在生产环境中大规模使用。这一年中,团队累积了很多经验,尤其在 cluster deployment / release / hot upgrade / rolling upgrade 方面 —— 2018 年 3 月份我会在旧金山的 Code BEAM 2018 大会上谈谈我们在这些方面的收获,希望大家捧场。&/p&&p&学一门新的语言并非学习它的语法那么简单。去年年初我写下了 &a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dfe6ca628aff62f2bf84fe2%26chksm%3D8704aaeebd6d04fd7bcad67%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何使用一门新的语言&/a&,介绍了我的一些思考。它不仅仅适用于 elixir,也适用于其他的语言。&/p&&p&如果你对 elixir / erlang 感兴趣,那么, &a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D9fb32f43ecechksm%3Dfcb76b9eea929eaf18dcb5a0bacb69a13ebd%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Let it crash:因为误解,所以瞎说&/a&,&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dae805b1b7c41bcfbffe2bcbf992b87db%26chksm%3D223e8ffb831d1ef7bfff0e4b4dce760cdbcdfd6e6d548a%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Phoenix 1.3,迈向正确的道路&/a&,&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D8dd16470ef6eed9d3ad8ec%26chksm%3Dadcde4491826eeec020f4bbebb8be74d%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&上帝说:要有一门面向未来的语言,于是有了 erlang&/a&,你也许不想错过。&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D8c68f89f51a48a0e11ec52aachksm%3D8704aae6bb709cd20e948fc516fbd858d0c439b5c014eea74ea9accbscene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何用正确的姿势打开 TDD 这篇文章&/a&,详细地探讨了我使用 TDD 的一些心得,里面还涵盖了很多和 design/arch 相关的思考。&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D76b275e9cca963bedca7564%26chksm%3D22a944dcccc315ed852abbf5fa3f9084ae%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&是时候想想怎么删除代码了&/a& 是一篇很有争议的文章,但他给你一个独特的视角考虑如何写出更好的代码。如果你赞同 Begin with end in mind,那么,我们要好好考虑这个问题:&b&有没有可能,我们在架构之初,就考虑到这个代码有可能在将来成为一种负债,因此在设计上考虑到如何能轻松地将其删除或者替换?&/b&&/p&&p&去年 3 月份,我参加了 erlang solutions 的一个 OTP 培训,写下了这样的文字:&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dd516adchksm%3D70b465e37bf64c932aca98c36be01baaescene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&当我参加培训时,我在想些什么?&/a&同样的一件事,不同人眼里有不同的价值,就看我们怎么样去发掘了。&/p&&p&很多人写了很多代码。但是,绝大多数人读过的代码还没有自己写过的代码多。这是一个很奇怪的现象 —— 我们从小到大,少说也读了几百几千万字的书,工作数年甚至十数年,还没有读过同样体量的代码。&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D9d8fedb0aecd05dedc3b%26chksm%3Dbf7daaba56cb4dd611dade9007dac35f73f233cscene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&为什么我们要阅读源码?&/a&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dce7d11fdf23bb7b76d95a%26chksm%3Daedefe1ae21d6b546b6288%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何阅读一份源码?&/a&希望能让你重燃对读优秀代码的兴趣。&/p&&p&提高软件开发的能力,除了多读代码之外,还要下苦功夫。&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Df15ed2e9fc5b2a88d35b8a%26chksm%3D8704abc1bdb27d6adcbbf2bcb5bbca02971dded0d0e2ffbc8%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&在提高代码能力这事上,没有银弹&/a& 就是这个意思。停下来,歇口气,造轮子 告诉你,没完没了打零工(do chores),如果不能把它们串起来,时不时来个从零到一,你会陷入 &b&你以为你知道了但其实你并不知道你不知道的&/b& 的窘境。&/p&&p&软件开发是个从起点到终点的高级寻路游戏,考究的是个解决问题的综合能力 —— 虽说条条大路通罗马,但有的路一马平川势如破竹,有的路如临深渊如履薄冰。我们要寻找的是时间空间俱优,还节省开发效率的妥协(compromise)之路。妥协不是件简单的事情 —— Rich Hickey 说,&b&你起码要有两个以上的 solution,才谈得上妥协&/b& —— 所以,见识丰富必不可少。也许下面几篇文章可以帮到你:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D1d7da4a332c267a625eee7%26chksm%3D8704abf7b07322e17ebcfedecaac3f112b0e%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&bash 的威力&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dd370f79f5c82bbe1a74c%26chksm%3D8704aba6bd950b2eed3989cbff65b0cddbc84857cdd469ca5a414b74f%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&谈谈状态机&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Db8ea0e7d62d747cd483fd8%26chksm%3Da06b68f09bee5fc43cc877d0e20b8ff%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&谈谈数据结构&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D8d55f97bcb33a80f11c59%26chksm%3Ddc57c17f38ca8d75ee9d9e8fe0beaa0d%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&谈谈边界&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Db4ddac46753b%26chksm%3Dffa33e2bd266b51c48cdf67d91ca807fdfcca022d30a786%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&思考:快与慢&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Debbd4ade70%26chksm%3Dbbbaef4d921fe65fe82cfba9cfe%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&service performance 101&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D176ebdf7a9%26chksm%3Dd71e5b31b405fa9c10ab11c3c86b3be0c542dd%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浪费内存?多大个事?&/a&&/li&&/ul&&p&看技术文章看累了,换换脑子,我们扯扯淡:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D2ddff68dab11ab3f5db02be%26chksm%3D8704abecb0d97b89cdb25fe2c005a6fbf92e5f3facbb%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&美帝面试二三事&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dececdca36c7285fb77dfceb%26chksm%3D3211cfcc2bf6f942e2d7c0b2a2f361c66de8eb81085a6acf6a0ef%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&社会我梅姐:美女兼劳模&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D9fc11a3b46bd5edad3c4%26chksm%3D8704aba0bb39b7aad80fa1fd918ce08daaccb0a5dbf6ecef5497%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&软件工程师成长之路&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dc96d8a72eb45a35f15b9af%26chksm%3D3226847dca3ccdd95f9bf6a9ab3c9a51bfea0e83efda%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&创业公司如何组建技术团队&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dcc684acad753dcd%26chksm%3Dc1cf5c5bb3d03bcb4a0f5c64ff35c7%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&程序员为什么会忧虑自己的未来&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D8b1cb439ab0e705dd6e8e9%26chksm%3D8704abf8b07322eee8aecb3bd6ad6f71f2673072feb0ed5b6f2f2fee97f0b0def%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&程序员的好日子何时才能到头?&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D50adb3d5b912e19bc98ad67%26chksm%3D309dec7ea000%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不要等客户来通知问题&/a&&/li&&/ul&&p&或者开拓一下视野:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D1b5ee89840ccb9c59ec971bd6fchksm%3D8704abb1bed9cdcd01ed9d9e68ae30f7ea97f95646edafc2c4scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&red,不红不专,但性感&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D122c74dfb32eefc5f9dc9aa648f16b98%26chksm%3D8704abdab0fffed1ce34cb56e82e5f58bbb87ascene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&sound of silence:数据传输的小众黑科技&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D7eba72f775dde454d89a0ce%26chksm%3D8704abceb07322d8baccfceb72c0c4a4bfa69fcd%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&闲扯比特币套利交易系统的设计&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D1d736cfe77ed32babf58ed955f50c2fc%26chksm%3D224fdfdabe140efcb7fcba010%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&alexa:梦中的女神&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3De8f12ccbe6d02c4cd5a82e86%26chksm%3D8704abe2b07322f4fdf8cce03fdac717aafba13f3f11996%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&pixel 2 XL:软件为王&/a&&/li&&/ul&&p&或者回顾一下 2017 年发生的灾难性大事件,以史为镜:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D7cc4aaa1f0a9cdb%26chksm%3Dbd38bdbd50b2dc7ff951ffa61b33fd8e%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从 gitlab 事件中吸取的教训&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Df52fachksm%3Da5a1f36c6d74b083b9bacb7f0dd6bb87e6e%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&北美互联网哀鸿遍野:号称 99.9% 可用性的 S3 挂了&/a&&/li&&/ul&&p&然后,躺在懒人沙发上,想想,作为一个程序员,自己眼中牛逼的自己该是什么样?如果没头绪,参看程序君吐血推荐的这篇:&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Db10f3d0979fd5eda86ebb656fd38186d%26chksm%3D220f1b4d18cb0aabcb1b4fc34bc0ffa85df1a73bac7502befe8ce8%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&程序员字典:「牛逼」&/a&。然后,再想想。&br&&/p&&p&2018 我会格外忙一些 —— 过去几年输入和输出都不算少,但主要在夯实自己的舒适区。2018 我将会深入踏足一些之前我只有粗鄙认知的领域:ML/DL 和 blockchain (主要是基于智能合约的去中心化应用)。我报了些线下和线上的课程,一季度每周大概有 10 个小时要用来上课,估计也要用同样体量的时间来夯实所学。所以我的原创文章产量会大大削减,争取每旬一更,最差也要双周更。请大家体谅。&/p&&p&希望这些文章能对对你有用。&/p&&p&往期串烧:&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3D%26idx%3D1%26sn%3Dc7c8a2d4d638fb8eb3d4%26chksm%3D8704aaf6b3fbfdd0b9cbfbe2c%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&2016 程序人生大串烧&/a&&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3NDM0ODQwMw%3D%3D%26mid%3Didx%3D1%26sn%3Dd22edfdf8ae%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&2015程序人生大串烧&/a&&/p&&p&&/p&
从 2014 年第一篇公众号文章开始,三年多时间我竟然已经写下了 386 篇文章,涵盖技术,管理,创业和一些莫名其妙的感悟。这便是小小的坚持迸发出的能量:不经意间,日拱一卒的零零碎碎汇集出这般美妙的结果。我常说:读自己的日记,仿佛在跟过去的自己对话…
&p&题主的标题让我想起了一篇文章,是一个华人开发者Allen Chou在顽皮狗公司开发神秘海域4时候的一些杂记。里面很大篇幅介绍了他参与的AI部分实现细节。&/p&&p&&a href=&//link.zhihu.com/?target=http%3A//allenchou.net/2016/05/a-brain-dump-of-what-i-worked-on-for-uncharted-4-chinese/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&我的Uncharted 4開發雜記&/a&&/p&&p&可以管中窥豹(但愿不是盲人摸象)式地体会下当今AAA大作的AI是怎么实现的。&/p&
题主的标题让我想起了一篇文章,是一个华人开发者Allen Chou在顽皮狗公司开发神秘海域4时候的一些杂记。里面很大篇幅介绍了他参与的AI部分实现细节。可以管中窥豹(但愿不是盲人摸象)式地体会下当今AAA大作的AI是怎么实现的。
&figure&&img src=&https://pic1.zhimg.com/3ba38c19d8c7bdaf3af7_b.jpg& data-rawwidth=&900& data-rawheight=&651& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic1.zhimg.com/3ba38c19d8c7bdaf3af7_r.jpg&&&/figure&&h2&&b&背景&/b&&/h2&游戏中的AI,大多数都是按照规则设定好的,没有太多花哨的技术。原因有几个:&p&一是出于风险成本的考虑,用一个新技术,需要程序员开发相应的算法和框架,游戏设计师重新上手设计方法和摸索算法的适用范围,小团队承受不起这样的开销,大团队又怕做坏名声;&/p&&p&二是“高级”的AI算法并不直观,难以设计。举一个例子,怎么利用神经网络来训练一个士兵AI?我见过的一个例子是设计师用几个按键来操作士兵移动攻击,然后程序自动记录敌我双方的数据和设计师的操作,最后利用这些信息作为input构建一个行为树。这个方法的问题有三个,一是效率奇慢,因为如果数据不够,行为树就可能覆盖不了所有情况,但多少才是“够”,又没有定论;二是错误的操作也会被记录下来,当然可以开发一个功能来删除设计师的某个动作;三是行为树的结果是无法解释的,相当于一个黑箱。&figure&&img src=&https://pic3.zhimg.com/dd2bc166b607642daf3df95db47bada4_b.jpg& data-rawwidth=&800& data-rawheight=&600& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic3.zhimg.com/dd2bc166b607642daf3df95db47bada4_r.jpg&&&/figure&&br&&/p&&p&由于上述的原因,一般的公司都会使用比较传统的有限状态机。&/p&&p&虽然第一次听的话可能会拗口,其实有限状态机的意思其实很简单,它包含了有限个的状态和状态间的转换条件。最直白的说法就是几个if...else...语句。为了弄明白这个概念,我们讲一个英雄的故事:&/p&&p&从前有一个胆小如鼠的英雄,&/p&&ol&&li&他看到哥布林就会跑过去打它;&/li&&li&他看到半兽人就会逃跑;&/li&&li&他看不到哥布林也看不到半兽人就会休息;&/li&&li&他看到哥布林也看到半兽人也会跑。&/li&&/ol&&p&我们可以从中抽象出这样的一个有限状态机:&/p&&p&&figure&&img src=&https://pic1.zhimg.com/6e30c3ddbfe5b6f7f5ecae_b.jpg& data-rawwidth=&946& data-rawheight=&433& class=&origin_image zh-lightbox-thumb& width=&946& data-original=&https://pic1.zhimg.com/6e30c3ddbfe5b6f7f5ecae_r.jpg&&&/figure&有限状态机很符合我们的认知,但它有一个致命的缺点——它随着状态和转换条件的增多而急速地变得错综复杂,以至于很难对它做出改动(想象一下,多加一个状态,则需要增加几条转换线,越多状态,需要增加的转换线越多)。&/p&&p&也由于这个原因,比较多的开发者投入了行为树的怀抱。&/p&&br&&br&&h2&&b&行为树&/b&&/h2&&h2&定义&/h2&&p&行为树的概念会比状态机要复杂些——行为树是一个包含逻辑节点和行为节点的树结构,每次需要找出一个行为的时候,会从树的根节点出发,遍历各个节点,找出第一个和当前数据相符合的行为。&/p&&p&很拗口对吧,下面来一个生动点的解释,继续上面的英雄的故事,但是是用行为树表达出来:&/p&&figure&&img src=&https://pic4.zhimg.com/eae63abffd0d577e2f4c_b.jpg& data-rawwidth=&960& data-rawheight=&720& class=&origin_image zh-lightbox-thumb& width=&960& data-original=&https://pic4.zhimg.com/eae63abffd0d577e2f4c_r.jpg&&&/figure&&p&这个行为树是等价于之前的有限状态机的。其中&/p&&p&&b&Root&/b&是根节点,每次需要寻找行为的时候都必须从这里开始。&/p&&p&&b&Priority Selector&/b&是一个逻辑节点,它的意思是让从左到右遍历自己的子节点,如果子节点的准入条件符合信息的话,就执行该子节点。如果英雄只看到哥布林,那么Orc in sight这个准入条件不符合,Escape不执行;Globlin in sight符合,于是执行Fight;因为Fight在Idle的左边,所以Fight的优先程度更高,于是Idle不执行。在我们的例子中,Idle可以看作是default behavior。&/p&&h2&优点&/h2&&p&从简单的行为树和有限状态机的对比,我们就可以看出,行为树由于引入了逻辑节点,它的转换条件更加少(线更少,更清晰),让&b&拓展AI变得更加容易&/b&。&/p&&p&行为树还有另外一个优点:行为的&b&重用&/b&(reuse)。&/p&&p&例如,Escape有一个跑的行为,而Fight则有跑的行为,和砍怪的行为。请看图:&br&&figure&&img src=&https://pic4.zhimg.com/edb6af3576ee_b.jpg& data-rawwidth=&953& data-rawheight=&726& class=&origin_image zh-lightbox-thumb& width=&953& data-original=&https://pic4.zhimg.com/edb6af3576ee_r.jpg&&&/figure&&/p&&p&&b&Sequence&/b&同样是一个逻辑节点,它的意思是从左到右按顺序执行子节点,并且仅仅在一个子节点执行完成后才执行下一个子节点。在例子中,Do Run需要有一个自己判断到达目的地的方法,当该方法返回end的时候,才会执行Do Slash。&br&&/p&&p&Escape和Fight的Do Run行为节点是一样的,只是Fight多了一个Do Slash行为节点而已。所以Do Run是一个可以重用的节点。&/p&&p&在行为树中,我们能够编写好Do Run,Do Slash这些基础的行为节点,和设定一些准入条件,就可以&b&组成千变万化的AI&/b&了!&/p&&p&我们希望英雄在逃跑的时候群众发出嘘声,而在攻击的时候出现欢呼声:&/p&&p&&figure&&img src=&https://pic2.zhimg.com/f33cbde92ce4c10408b3dea_b.jpg& data-rawwidth=&960& data-rawheight=&720& class=&origin_image zh-lightbox-thumb& width=&960& data-original=&https://pic2.zhimg.com/f33cbde92ce4c10408b3dea_r.jpg&&&/figure&省略了其他部分,只画Escape部分。&/p&&p&Parallel是一个逻辑节点,它的意思是让所有子节点同时运行,那它什么时候结束呢,可以使当所有子节点都完成的时候结束,也可以让任一子节点完成时结束,视乎需要来做出选择。&/p&&p&那么在攻击当中会是怎么样实现的呢?大家可以尝试画出来,习惯一下行为树的思维方式。&/p&&br&&br&&h2&总结:&/h2&&ol&&li&行为树拥有3种节点:&/li&&ol&&li&根节点 Root&/li&&li&逻辑节点(可拓展):&/li&&ol&&li&Priority Selector&/li&&li&Sequence&/li&&li&Parallel&/li&&/ol&&li&行为节点&/li&&/ol&&li&行为树在复杂的情况比有限状态机更清晰,更可拓展&/li&&li&行为树有利于逻辑的重用&/li&&li&设计得好的行为树可以千变万化!&/li&&/ol&&br&&p&之后,我会展示在游戏开发中怎么利用行为树作为框架来使用。&/p&
背景游戏中的AI,大多数都是按照规则设定好的,没有太多花哨的技术。原因有几个:一是出于风险成本的考虑,用一个新技术,需要程序员开发相应的算法和框架,游戏设计师重新上手设计方法和摸索算法的适用范围,小团队承受不起这样的开销,大团队又怕做坏名声…
&figure&&img src=&https://pic4.zhimg.com/v2-5d40222afe5c047f344a499c_b.jpg& data-rawwidth=&658& data-rawheight=&439& class=&origin_image zh-lightbox-thumb& width=&658& data-original=&https://pic4.zhimg.com/v2-5d40222afe5c047f344a499c_r.jpg&&&/figure&&h2&&b&1. 总体介绍&/b&&/h2&&p&要做个Demo,结果又碰到个比较生的领域——怎么做出我想要的动画状态机,这里面包括了几个我不是很懂的方面:如何划分动作使用情形?需不需要用Blend Tree及怎么使用?动作间的过度怎么搞?变量的一些细微区别?&/p&&br&&h2&&b&2. 拿到一些Animation Clip,如何在不知道游戏规则的前提下,分门别类?&/b&&/h2&
下图是我拿到Animation Clip,开始看到它们的时候我的内心是崩溃的(此处应有表情包,可惜我没有……)。&p&(图1)&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-30829cfbfecc1bbff822_b.jpg& data-rawwidth=&127& data-rawheight=&283& class=&content_image& width=&127&&&/figure&&p&我感觉这些应该是在某种游戏规则下才能搞定的分类,如战斗或非战斗两大类,可我目前还没确定游戏规则(希望在做出最小系统的情况下,用系统套规则,而不是直接上特定的系统,这样的好处是将来换个规则我还能用大部分系统)。&/p&&p&所以目前情况是没有策划案就要写代码,怎么办?运用“奥卡姆剃刀”原理(如无必要,勿增实体),首先分为人是生是死两大类,在生的情况下,再根据传统游戏经验,分为持续动作和非持续动作两大类,分到这里就可以了,再下去就是具体游戏规则的调用了。&/p&&p&&u&&b&注意:&/b&&/u&&/p&&p&1) 这里写的很简略,但当时做的时候非常纠结,心里老是预设游戏规则,一直陷在战斗和非战斗两大类里,折腾来折腾去没有头绪。&/p&&p&2) 我也找了教程看其他人怎么做的,可惜那些动作都非常有自我针对性,一般都是拿对称动作举例,如向左跑、向右跑,后来只好请教别人,知道了“奥卡姆剃刀”后,才想出这个分类法。&/p&&h2&&b&3.
知道分类后,判断需不需要Blend Tree?&/b&&/h2&&p&
下图是我提出的分类法实例展示。&/p&&p&(图2)&/p&&figure&&img src=&https://pic3.zhimg.com/v2-c183b265d291e393b9e93ad_b.jpg& data-rawwidth=&875& data-rawheight=&519& class=&origin_image zh-lightbox-thumb& width=&875& data-original=&https://pic3.zhimg.com/v2-c183b265d291e393b9e93ad_r.jpg&&&/figure&&p&虽然在网上找的资料对我分类动作没有帮助,不过倒把Blend Tree给学习了一下。&/p&&p&持续性动作包括很多:Walk,Run,Dash很明显是因为速度不同(典型的控制单一变量)而产生的不同动作,所以非常适合用Blend Tree(1D)来实现,最终我又把持续性的动作分为了Stay和Move两种,一种保持在原地,一种需要移动。&/p&&p&&u&&b&注意:&/b&&/u&&/p&&p&&u&1) 究竟要不要把Idle算到Move这个Blend Tree里?&/u&&/p&&p&纠结这点是因为很多视频教程都算进去了,但是他们和我的动作区别是,我这边除了速度为零的Idle,还有Defend等这些动作,这些速度也为零,但除此之外和Walk就没有共同点了,我尝试了硬把Defend放进去,把Blend Tree Type设置为2D Freeform Cartesian(横纵坐标不代表方向,而是自设的变量),结果复杂无比不说,动画也很奇怪,最后就把Defend、Upset、Victory、Idle放到Stay这个子状态机里。&/p&&p&&u&2) 关于Blend Tree Type的一些解释&/u&&/p&&p&&i&1D&/i&——只根据一个变量就能改变的几种动作,通常是速度或角度。&/p&&p&&i&2D Simple Directional&/i&——可以在众多方向上设置动作,但是每个方向只能代表一个动作,另外千万不要认为只能在横纵坐标上设置动作。&/p&&p&&i&2D Freeform Directional&/i&——也可以在多方向上设置动作,但每个方向可以代表多个,就是说每个方向是一个1D。&/p&&p&&i&2D Freeform Cartesian&/i&——横纵坐标的意义可以自己设置,也可以有多方向,当时我为了把Idle、Defend合进去,就把横纵标设为speed,纵坐标设为StayType。&/p&&p&&i&Direct&/i&——首先每个动作要设置一个变量,每个动作根据这个变量的权重来互相影响。&/p&&p&注意一个小问题:设置的变量只能用float型,我也不知道为什么。&/p&&h2&&b&4. 子动作状态机之间的变量设置及连接&/b&&/h2&&p&
变量设置如下图&br&&/p&&p&(图3)&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ac63b7b3c541cb69f12d2679bdc7a869_b.jpg& data-rawwidth=&301& data-rawheight=&127& class=&content_image& width=&301&&&/figure&&p&解释(从上到下):&/p&&p&根据人物是否活着分类,肯定需要个布尔值来判断;图2中,Stay子状态机里有多个动作,要区分只能用一个int型了;不能持续的动作,只触发一次用trigger,区别触发哪个也是用int;最后一个speed用来在Blend
Tree里控制不同的移动。&/p&&p&&u&1) 动作之间的连接&/u&&/p&&p&从图2大方面说:一开始必定是触发Stay里的默认状态Idle;任何状态都会触发Die或OnceAction里的动作,都需要两个条件(isLive和triggerOnceAction),它们只是isLive条件不同;Stay和Move里动作的切换通过判断speed是不是为0.001;最后Die和Stay直接一定要连接(isLive==true),否则从复活后就回不到默认Idle了。&/p&&p&&u&&b&注意:&/b&&/u&&/p&&p&a)
从Any State到Die,除了判断isLive==FALSE之外,一定要加上triggerOnceAction这个条件,否则人物死亡会一直重复动作Die,因为Any State状态里也包括Die,就是说死亡后又判断条件,结果符合就继续死亡动画,用trigger来控制,我的理解是trigger能保证动作只能执行一次。&/p&&p&b)
为什么speed==0.001,而不是0?因为误差,这个小数点后几位是自己调出来的。&/p&&p&&u&2) 从小的方面来说&/u&&/p&&p&(图4)&/p&&figure&&img src=&https://pic4.zhimg.com/v2-20073bedd9e5d0d1153c7bba46e396b0_b.jpg& data-rawwidth=&1032& data-rawheight=&757& class=&origin_image zh-lightbox-thumb& width=&1032& data-original=&https://pic4.zhimg.com/v2-20073bedd9e5d0d1153c7bba46e396b0_r.jpg&&&/figure&&p&(图5)&/p&&figure&&img src=&https://pic2.zhimg.com/v2-bf2dfb07dea_b.jpg& data-rawwidth=&1013& data-rawheight=&667& class=&origin_image zh-lightbox-thumb& width=&1013& data-original=&https://pic2.zhimg.com/v2-bf2dfb07dea_r.jpg&&&/figure&&p&&u&为什么有的动作用橘色表示?&/u&&/p&&p&首先整个状态机必须只有个一个默认状态,这个默认状态用橘色表示,图2中,这个动作在Stay-Idle上,所以图5中,就算动作通过trigger触发了一次后也可以自动回到Idle上。&/p&&p&&u&为什么图4,图5中有的transition的线是深橘色,并且有多个箭头?&/u&&/p&&p&深橘色表示连接到默认动作,但是如果外部有变量控制得话,默认会不起效果,如图5中的状态;多个箭头表示这上面有多个transition或有transition脚本。&/p&&p&图4中,从Entry到每个动作、每个动作间的transition就是stayState的切换;从每个动作到Exit,条件就变为speed&0.001。&/p&&p&&u&为什么图4出Stay状态机的条件仅仅是速度?&/u&&/p&&p&因为这个圈子包括了整个状态机的默认状态,打破这个平衡就两个条件:要不去执行OnceAction里某个动作,但是执行完了还会回来;要不就是变到另一种持续状态,速度不为零的某个运动状态,然后保持住。前一种状态有Any State来保证了,所以这里就不需要再写。&/p&&p&图5中,从Entry到每个状态,只需要判断OnceActionType的int值,出去不用做什么判断,因为(再强调一遍)这里的动作都是用trigger触发的,注意这里,如果没有连接各个动作到Exit的话(这里的transition不需要有条件),执行一遍这里动作就回不到默认Idle动作了,因为没有出口。&/p&&p&到这里,(其实中间的每一步都和别人讨论了很久)一个比较复杂(不是轴对称动作)的状态机就完成了。&/p&&br&&br&&p&三个星期没更新专栏真是抱歉了呢~Blender上手虽然比较快,但是我离熟悉还有段距离。&/p&&p&给你们看看我的成果,一个low-poly的牛仔,讲真,蛮自豪的呢~也就新手班排名前五吧!&/p&&figure&&img src=&https://pic3.zhimg.com/v2-a538bfb2fc_b.jpg& data-rawwidth=&484& data-rawheight=&842& class=&origin_image zh-lightbox-thumb& width=&484& data-original=&https://pic3.zhimg.com/v2-a538bfb2fc_r.jpg&&&/figure&&br&&p&&b&&i&最后想说点政治不正确的话&/i&&/b&&/p&&p&开专栏了这么久,会遇到一些热心网友给我的各种留言和私信,我其实挺感激的,因为代表了他们对你的信任,中间有我能回答的我第一时间看到后都会回答,希望能力所能及的帮上忙,可是呢,总会有不太开心的情况出现。&/p&&p&第一种比较常见的就是,没头没脑的问你“我没实现XXX这是为什么”,问出这种问题的,通常是学生或刚工作没多久的人,首先我建议你读一本书叫《学会提问》,同时请问你,不知道你任何操作步骤的情况下我怎么回答你,什么都不描述,你就是在知乎发个问题,请个高手来回答,我估计喷你的可能性会高一些吧。我也关注了一些大神回答一些比较初级的问题,能回答的都是问题本身是有理有据,有详细的步骤或代码描述的。&/p&&p&第二种,我不回答用Google能搜出来的问题,因为没什么好回答的,如“请问XXX是什么/怎么配置/怎么实现?”&/p&&p&第三种,目前碰到单例,十分让我不爽,一定要我当时帮他解决某某问题,还说这问题一定对我来说很简单,我就问你你的判断标准是什么?!你怎么知道有我空没空呢?!我客气得表示目前没空,就不理我+把我删了,真没礼貌呢小伙子!&/p&&p&我以前在知乎或者某学习研究群里也问过问题,最终的结果是别人能帮你的真的很少,就算帮能不能帮到点上也很愁人,因为要描述清楚问题怎么出现的,出现在哪,整个问题的流程是个需要功力的活,往详细的讲,大家的注意力和精力很宝贵,没空看,往简略的讲,大家最多给你个可能的方向,怎么解决还是得靠自己。&/p&&p&目前,我在学习中也遇到很多问题,往近了说就是学Blender的时候,各种对新手来说很神奇的坑,我只有靠我自己的英文水平和翻Google的能力,那种实在太特定并且复杂的问题,推荐当面找熟人问吧!&/p&&p&我目前还在学习英文,虽然体力不如以前,但是分析能力上了很大一个台阶,感觉英语学起来不是那么枯燥难懂了,因为需要不停的去用、去练,当我能听懂YouTube上的视频时,成就感爆棚啊!~&/p&&br&&p&好了,不小心扯了这么多,本篇就到这里,欢迎您的收看,我们下次再见!~&/p&
1. 总体介绍要做个Demo,结果又碰到个比较生的领域——怎么做出我想要的动画状态机,这里面包括了几个我不是很懂的方面:如何划分动作使用情形?需不需要用Blend Tree及怎么使用?动作间的过度怎么搞?变量的一些细微区别? 2. 拿到一些Animation Clip,如…
&p&这样,我有一个大胆的想法。&/p&&p&我从今天(10月17号)开始,从零起步制作一个 2D 横版像素游戏。暂定为期一个月,中间的制作过程就更新在这个答案里。&/p&&p&过程中,如果有什么比较好用的教程、资料,也一并更新于此。&/p&&p&&b&一个月后,告诉你完整的「一个2D横版像素游戏的制作流程」。&/b&&/p&&p&(对了,使用的引擎是 Unity3D)&/p&&p&&br&&/p&&p&最终的成品,做到哪儿算哪——不要期待太高,但争取能完整地过一遍基础流程。&/p&&p&(其实对于一些有经验的人来说,一周末的 Game Jam 就够完成这个目标了。但我很久没碰游戏引擎,许多坑都得从头踩起,所以放宽些时间吧。)&/p&&p&在那之前,就先保持着匿名。&/p&&blockquote&日 02:14:30 开搞&/blockquote&&hr&&p&呼,看了楼上的精致回答有点虚。顺便也感谢经验分享!&/p&&p&不过我接着做我的……&/p&&p&刚才试着画了个角色动图。是不是主角?不知道。可能只是背景君吧。&/p&&p&严格来说并不算「像素」……虽然是用的PS里的铅笔工具。随手涂的太糙了。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-a1b7e8da86_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&294& data-rawheight=&233& class=&content_image& width=&294&&&/figure&&p&打算是&b&先凑合着准备一波资源&/b&,把重心放在开发过程上。&/p&&p&那,就酱先。&/p&&blockquote&日 02:39:23&/blockquote&&hr&&p&赞数涨的有点儿厉害啊……果然游戏是热门话题。&/p&&p&其实我不建议你们看到这么一个吹大话的答案就先给点赞的。万一我这是随口立 Flag 你们不就赞错人了吗。&/p&&p&&br&&/p&&p&说回正题。&/p&&p&今天开始试着画了一下场景图。这个阶段是最开心的啦,还没开工,没太多限制,可以随便开脑洞设想做什么样的游戏。边画边能构思「诶这个可以这样出来」、「这里主角可以那样」、「最后巴拉巴拉」——这种随意放飞阶段可以说是游戏制作过程里最开心的事儿了!&/p&&p&至于实现过程嘛……哈哈哈其实是长期打磨的辛苦活,倒未必有多少欢乐的。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-28613bb6ffebb916ca7139_b.jpg& data-size=&normal& data-rawwidth=&640& data-rawheight=&360& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic2.zhimg.com/v2-28613bb6ffebb916ca7139_r.jpg&&&figcaption&脑洞中的场景构想图&/figcaption&&/figure&&p&可以看到,之前画的那个蠕动怪,暂时是设定成 BOSS 一类的角色。NPC 也说不定。&/p&&p&主角是左下角那个黑色的小球。加了呆毛,但感觉对动画来说可能会有不小的工作量,之后也许会删掉也说不定。&/p&&p&亮黄色个部件是用来给自己指示的,黄色矩形是主角的大小设定(40*40),橙色的是跳跃的高度(100+60),也就是二段跳最高跳到橙色的顶端,正好能跳上右边平台1号。&/p&&p&嗯,我自己玩横版游戏很喜欢二段跳的,所以做的游戏肯定也要有这个功能啦。&/p&&p&两侧那些线条是避免画面太空旷而加的前景来着。之后应该会随着镜头移动而一起晃动吧,增加景深。&/p&&p&&br&&/p&&p&今天想到的关于这个游戏的「参考游戏」,一个是《&a href=&//link.zhihu.com/?target=http%3A//store.steampowered.com/app/400630/Wuppo/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Wuppo&/a&》还有一个是《&a href=&//link.zhihu.com/?target=http%3A//store.steampowered.com/app/583470/The_End_Is_Nigh/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&The End is Nigh&/a&》;后者我没玩过,但是想试一下它一个关卡只包括在一个屏幕内 的思路;前者嘛……比起近战攻击,射击战斗好像比较容易实现的样子。&/p&&p&先说到这儿,接下来要想办法在 Unity 里搭建出这个场景啦!&/p&&blockquote&对了,说一个奇技淫巧。在 PS 里设定图像差值为 &b&邻近&/b&,然后把图片缩小几倍再放大回原尺寸,能有效增加「像素感」(其实就是锯齿啦,哈哈)&br&昨天画的那坨就做了这么个操作,放大看还挺明显的。不过这是我偷懒才只么干的,正儿八经的艺术家还是应该手动点像素哈。&br&感谢 &a class=&member_mention& href=&//www.zhihu.com/people/7c1a9c33e76303adc2fc59& data-hash=&7c1a9c33e76303adc2fc59& data-hovercard=&p$b$7c1a9c33e76303adc2fc59&&@十八&/a& 提供的情报!&/blockquote&&figure&&img src=&https://pic3.zhimg.com/v2-08e4e9ab8b2c430a110e6_b.jpg& data-size=&normal& data-rawwidth=&400& data-rawheight=&395& class=&content_image& width=&400&&&figcaption&缩小1/5再放大之后的效果&/figcaption&&/figure&&blockquote&日 22:57:01&/blockquote&&hr&&p&刚才折腾了一下怎么从 PS 里导出帧动画,这里也分享一下设置。&/p&&p&为了让导出来的图像素材正好是帧的数量,所以&b&把所有帧的时间间隔设为 1 秒,然后把帧速率设为 1 FPS&/b&;如果想要导出透明底色的图片,选择 PNG 格式,右下角 Alpha 通道选择「预先进行白色正片叠底」。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-d7fa3ea9ca8cea4e78a63bd_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&832& data-rawheight=&659& class=&origin_image zh-lightbox-thumb& width=&832& data-original=&https://pic2.zhimg.com/v2-d7fa3ea9ca8cea4e78a63bd_r.jpg&&&/figure&&p&参考:&a href=&https://www.zhihu.com/question/& class=&internal&&ps 如何批量导出动画所有帧?&/a&&/p&&blockquote&日 23:25:02&/blockquote&&hr&&figure&&img src=&https://pic2.zhimg.com/v2-f77ef3f7c9dbd57853d9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&230& data-rawheight=&352& class=&content_image& width=&230&&&/figure&&p&那,开始在 Unity 里捏小人儿了。经过一番自己夏姬八折腾,给角色加上了 Animation,抖起来很鬼畜。你看到的 GIF 效果是减速过的,游戏里刚启动出来是 60fps 的狂暴颤动效果。&/p&&p&好,那今晚先到这儿,明天继续搭场景+捏小人儿~&/p&&blockquote&日 23:59:56&/blockquote&&p&没忍住,接着调了点儿,现在可以从天而降了。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-266cfa6ff50667dbbf341a0_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&374& data-rawheight=&262& class=&content_image& width=&374&&&/figure&&blockquote&日 00:12:11&/blockquote&&hr&&p&好久不见!我又来更新啦~咕咕了两天不好意思嘿。&/p&&p&昨天在亚马逊上买了两本书,今天就到了。都是神往已久的游戏设计方面的书籍。《游戏设计艺术》和《游戏设计梦工厂》,算上优惠平均下来每本只要60元噢。&/p&&p&说正题,今天试着实现了“子弹”的雏形。因为主角工程量会比较大,留到之后再做。先尝试做出&b&「子弹打在敌人身上,闪现红光,敌人扣血,子弹消失」&/b&的功能吧。&/p&&p&然后目前完成的是……「创建超多子弹」,哈哈。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-e041c4decfdfe2a88d31c813e3b5c981_b.jpg& data-size=&normal& data-rawwidth=&294& data-rawheight=&233& class=&content_image& width=&294&&&figcaption&Unlimited Bullet Works——无限弹制!&/figcaption&&/figure&&p&倒放是 GifCam 里实现的,并不是游戏内效果。但是看起来很有意思,之后也想办法用代码实现这个功能吧ww&/p&&blockquote&&i&日 23:59:39&/i&&/blockquote&&p&希望子弹是全方向的,所以做了这个功能。现在可以朝整个屏幕内随意开火啦!&/p&&figure&&img src=&https://pic4.zhimg.com/v2-8de64f70fa_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&345& data-rawheight=&194& class=&content_image& width=&345&&&/figure&&blockquote&参考资料:&a href=&//link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3D47xWM1RcY3Y& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&[Unity C# Tutorial] : 360° Aiming in a 2D Platform.&/a&&br&日 14:07:05&/blockquote&&figure&&img src=&https://pic4.zhimg.com/v2-3f5b8edbd25dda10fca2d25d256b8c5f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&160& data-rawheight=&160& class=&content_image& width=&160&&&/figure&&p&咕咕咕……!&/p&&p&向组织汇报一下……&/p&&p&吹完牛的四个星期里,一个周末加班,两个周末玩儿《刺客信条·起源》,最后一个周末玩儿《马里奥·奥德赛》。&/p&&p&所以,我理解为啥一个做游戏的前辈说他自己很少玩游戏了。&/p&&p&一旦玩了别的好游戏就很难抽出时间(和足够的意志)去做自己的游戏了啊!!&/p&&blockquote&日 08:33:34&/blockquote&
这样,我有一个大胆的想法。我从今天(10月17号)开始,从零起步制作一个 2D 横版像素游戏。暂定为期一个月,中间的制作过程就更新在这个答案里。过程中,如果有什么比较好用的教程、资料,也一并更新于此。一个月后,告诉你完整的「一个2D横版像素游戏的制…
我厂是用Spring+Netty+RamCache+MySQL改造成自己的一套框架。&br&&br&框架的总体设计是这样的:&br&&div class=&highlight&&&pre&&code class=&language-text&&Framework
├─console
事件处理系统
├─protocol
对象传输协议
├─ramcache
数据库缓存
├─resource
静态资源管理
├─scheduler
├─socket
工具类集合
&/code&&/pre&&/div&&br&我们用框架写业务模块的时候是这样子的:&br&&div class=&highlight&&&pre&&code class=&language-text&&application
├─module
│ ├─event
│ ├─exception
│ ├─facade
外部接口(供前端调用)
│ ├─manager
数据库缓存操作
│ ├─model
│ │ └─result
返回结果对象模型
│ ├─resource
游戏数值配置表映射类(供策划)
│ ├─service
业务逻辑层
│ └─ModuleConfig.java
模块全局配置类
├─manager
管理后台接口
└─Start.java
&/code&&/pre&&/div&各个业务模块之间保持了非常低的耦合(公共模块除外,如背包系统、邮件系统等),各模块之间的调用由service层提供的接口。&br&&br&另外,可以看下 &a data-hash=&7e8e93ec706ad16c0b016& href=&//www.zhihu.com/people/7e8e93ec706ad16c0b016& class=&member_mention& data-editable=&true& data-title=&@庆亮& data-hovercard=&p$b$7e8e93ec706ad16c0b016&&@庆亮&/a&的回答:&br&&a href=&http://www.zhihu.com/question/& class=&internal&&为什么一些网页游戏喜欢用Erlang做服务端? - Erlang(编程语言)&/a&
我厂是用Spring+Netty+RamCache+MySQL改造成自己的一套框架。 框架的总体设计是这样的: Framework
├─console 总控制台
├─event 事件处理系统
├─protocol 对象传输协议
├─ramcache 数据库缓存
├─resource 静态资源管理
├─scheduler 定时任务
&figure&&img src=&https://pic1.zhimg.com/18dc7b70cd4a0f5bdcc8cabe_b.jpg& data-rawwidth=&640& data-rawheight=&400& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic1.zhimg.com/18dc7b70cd4a0f5bdcc8cabe_r.jpg&&&/figure&&p&项目的性能优化主要围绕CPU、GPU和内存三大方面进行。接上期&a href=&http://link.zhihu.com/?target=http%3A//blog.uwa4d.com/archives/optimzation_cpu.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&CPU优化&/a&专讲,我们本期和大家分享内存方面的优化心得。&/p&&p&无论是游戏还是VR应用,内存管理都是其研发阶段的重中之重。&/p&&p&然而,在我们测评过的大量项目中,90%以上的项目都存在不同程度的内存使用问题。就目前基于Unity引擎开发的移动游戏和移动VR游戏而言,内存的开销无外乎以下三大部分:&strong&1.资源内存占用;2.引擎模块自身内存占用;3.托管堆内存占用。&/strong&&/p&&p&如果您的项目存在内存问题,一定逃不出以上三种情况。今天,我们就这三种情况逐一进行解释。&/p&&h1&&strong&资源内存占用&/strong&&/h1&&p&在一个较为复杂的大中型项目中,资源的内存占用往往占据了总体内存的70%以上。因此,资源使用是否恰当直接决定了项目的内存占用情况。一般来说,一款游戏项目的资源主要可分为如下几种:纹理(Texture)、网格(Mesh)、动画片段(AnimationClip)、音频片段(AudioClip)、材质(Material)、着色器(Shader)、字体资源(Font)以及文本资源(Text Asset)等等。其中,纹理、网格、动画片段和音频片段则是最容易造成较大内存开销的资源。&/p&&h3&一、纹理&/h3&&p&纹理资源可以说是几乎所有游戏项目中占据最大内存开销的资源。一个6万面片的场景,网格资源最大才不过10MB,但一个的纹理,可能直接就达到16MB。因此,项目中纹理资源的使用是否得当会极大地影响项目的内存占用。&br&那么,纹理资源在使用时应该注意哪些地方呢?&/p&&p&&strong&(1) 纹理格式&/strong&&/p&&p&纹理格式是研发团队最需要关注的纹理属性。因为它不仅影响着纹理的内存占用,同时还决定了纹理的加载效率。一般来说,我们建议开发团队尽可能根据硬件的种类选择硬件支持的纹理格式,比如Android平台的ETC、iOS平台的PVRTC、Windows PC上的DXT等等。&strong&因此,我们在UWA测评报告中,将纹理格式进行详细罗列,以便开发团队进行快速查找,一步定位。&/strong&&/p&&figure&&img src=&https://pic4.zhimg.com/64ce69aafe6001ca7eef867eec13cf99_b.jpg& data-rawwidth=&2301& data-rawheight=&1024& class=&origin_image zh-lightbox-thumb& width=&2301& data-original=&https://pic4.zhimg.com/64ce69aafe6001ca7eef867eec13cf99_r.jpg&&&/figure&&br&&p&在使用硬件支持的纹理格式时,你可能会遇到以下几个问题:&/p&&blockquote&&ul&&li&色阶问题&br&由于ETC、PVRTC等格式均为有损压缩,因此,当纹理色差范围跨度较大时,均不可避免地造成不同程度的“阶梯”状的色阶问题。因此,很多研发团队使用RGBA32/ARGB32格式来实现更好的效果。但是,这种做法将造成很大的内存占用。比如,同样一张的纹理,如果不开启Mipmap,并且为PVRTC格式,则其内存占用为512KB,而如果转换为RGBA32位,则很可能占用达到4MB。所以,研发团队在使用RGBA32或ARGB32格式的纹理时,一定要慎重考虑,&strong&更为明智的选择是尽量减少纹理的色差范围,使其尽可能使用硬件支持的压缩格式进行储存。&/strong&&/li&&li&ETC1 不支持透明通道问题&br&在Android平台上,对于使用OpenGL ES 2.0的设备,其纹理格式仅能支持ETC1格式,该格式有个较为严重的问题,即不支持Alpha透明通道,使得透明贴图无法直接通过ETC1格式来进行储存。对此,我们建议研发团队将透明贴图尽可能分拆成两张,即一张RGB24位纹理记录原始纹理的颜色部分和一张Alpha8纹理记录原始纹理的透明通道部分。然后,将这两张贴图分别转化为ETC1格式的纹理,并通过特定的Shader来进行渲染,从而来达到支持透明贴图的效果。&strong&该种方法不仅可以极大程度上逼近RGBA透明贴图的渲染效果,同时还可以降低纹理的内存占用,是我们非常推荐的使用方式。&/strong&&/li&&/ul&&br&&p&当然,目前已经有越来越多的设备支持了OpenGL ES 3.0,这样Android平台上你可以进一步使用ETC2甚至ASTC,这些纹理格式均为支持透明通道且压缩比更为理想的纹理格式。如果你的游戏适合人群为中高端设备用户,那么不妨直接使用这两种格式来作为纹理的主要存储格式。&/p&&/blockquote&&p&&strong&(2)纹理尺寸&/strong&&/p&&p&一般来说,纹理尺寸越大,则内存占用越大。所以,尽可能降低纹理尺寸,如果512x512的纹理对于显示效果已经够用,那么就不要使用的纹理,因为后者的内存占用是前者的四倍。&strong&因此,我们在UWA测评报告中,将纹理的尺寸进行详细展示,以便开发团队进行快速检测。&/strong&&/p&&figure&&img src=&https://pic1.zhimg.com/dfabbbddae4f_b.jpg& data-rawwidth=&2287& data-rawheight=&985& class=&origin_image zh-lightbox-thumb& width=&2287& data-original=&https://pic1.zhimg.com/dfabbbddae4f_r.jpg&&&/figure&&br&&p&&strong&(3) Mipmap功能&/strong&&/p&&p&Mipmap旨在有效降低渲染带宽的压力,提升游戏的渲染效率。但是,开启Mipmap会将纹理内存提升1.33倍。对于具有较大纵深感的3D游戏来说,3D场景模型和角色我们一般是建议开启Mipmap功能的,但是在我们的测评项目中,经常会发现部分UI纹理也开启了Mipmap功能。这其实就没有必要的,绝大多数UI均是渲染在屏幕最上层,开启Mipmap并不会提升渲染效率,反倒会增加无谓的内存占用。&strong&因此,建议研发团队在UWA的测评报告中通过Mipmap一项进行排序,详细检测开启Mipmap功能的资源是否为UI资源。&/strong&&/p&&figure&&img src=&https://pic4.zhimg.com/40cfb8c6f132beb27e54dc_b.jpg& data-rawwidth=&2328& data-rawheight=&1019& class=&origin_image zh-lightbox-thumb& width=&2328& data-original=&https://pic4.zhimg.com/40cfb8c6f132beb27e54dc_r.jpg&&&/figure&&br&&p&&strong&(4) Read & Write&/strong&&/p&&p&一般情况下,纹理资源的“Read & Write”功能在Unity引擎中是默认关闭的。但是,我们仍然在项目深度优化时发现了不少项目的纹理资源会开启该选项。&strong&对此,我们建议研发团队密切关注纹理资源中该选项的使用,因为开启该选项将会使纹理内存增大一倍。&/strong&&/p&&figure&&img src=&https://pic2.zhimg.com/246edb7d264e11da994f92f245bed35e_b.jpg& data-rawwidth=&648& data-rawheight=&192& class=&origin_image zh-lightbox-thumb& width=&648& data-original=&https://pic2.zhimg.com/246edb7d264e11da994f92f245bed35e_r.jpg&&&/figure&&br&&h3&二、网格&/h3&&p&网格资源在较为复杂的游戏中,往往占据较高的内存。对于网格资源来说,它在使用时应该注意哪些方面呢?&/p&&p&&strong&(1) Normal、Color和Tangent&/strong&&/p&&p&在我们深度优化过的大量项目中,Mesh资源的数据中经常会含有大量的Color数据、Normal数据和Tangent数据。这些数据的存在将大幅度增加Mesh资源的文件体积和内存占用。其中,Color数据和Normal数据主要为3DMax、Maya等建模软件导出时设置所生成,而Tangent一般为导入引擎时生成。&/p&&p&更为麻烦的是,如果项目对Mesh进行Draw Call Batching操作的话,那么将很有可能进一步增大总体内存的占用。比如,100个Mesh进行拼合,其中99个Mesh均没有Color、Tangent等属性,剩下一个则包含有Color、Normal和Tangent属性,那么Mesh拼合后,CombinedMesh中将为每个Mesh来添加上此三个顶点属性,进而造成很大的内存开销。&strong&正因如此,我们在UWA测评报告中为每个Mesh展示了其Normal、Color和Tangent属性的具体使用情况,研发团队可以直接针对每种属性进行排序查看,直接定位出现冗余数据的资源。&/strong&&/p&&figure&&img src=&https://pic1.zhimg.com/5c2d2f84ca_b.jpg& data-rawwidth=&2292& data-rawheight=&988& class=&origin_image zh-lightbox-thumb& width=&2292& data-original=&https://pic1.zhimg.com/5c2d2f84ca_r.jpg&&&/figure&&br&&p&一般来说这些数据主要为Shader所用,来生成较为酷炫的效果。所以,建议研发团队针对项目中的网格资源进行详细检测,查看该模型的渲染Shader中是否需要这些数据进行渲染。&/p&&p&限于篇幅,我们今天只针对纹理和网格资源进行详细介绍,对于动画片段、音频片段等其他资源,建议您直接通过UWA测评报告中进行查看。同时,我们会在后续的资源专题中进行详细讲解,敬请期待。&/p&&h1&&strong&引擎模块自身占用&/strong&&/h1&&p&引擎自身中存在内存开销的部分纷繁复杂,可以说是由巨量的“微小”内存所累积起来的,比如GameObject及其各种Component(最大量的Component应该算是Transform了)、ParticleSystem、MonoScript以及各种各样的模块Manager(SceneManager、CanvasManager、PersistentManager等)...&/p&&p&一般情况下,上面所指出的引擎各组成部分的内存开销均比较小,真正占据较大内存开销的是这两处:&strong&WebStream&/strong& 和 &strong&SerializedFile&/strong&。其绝大部分的内存分配则是由AssetBundle加载资源所致。简单言之,当您使用new WWW或CreateFromMemory来加载AssetBundle时,Unity引擎会加载原始数据到内存中并对其进行解压,而WebStream的大小则是AssetBundle原始文件大小 + 解压后的数据大小 + DecompressionBuffer(0.5MB)。同时,由于Unity 5.3版本之前的AssetBundle文件为LZMA压缩,其压缩比类似于Zip(20%-25%),所以对于一个1MB的原始AssetBundle文件,其加载后WebStream的大小则可能是5~6MB,&strong&因此,当项目中存在通过new WWW加载多个AssetBundle文件,且AssetBundle又无法及时释放时,WebStream的内存可能会很大,这是研发团队需要时刻关注的。&/strong&&/p&&figure&&img src=&https://pic4.zhimg.com/b1e8d8b998ff470e3b998d_b.jpg& data-rawwidth=&2217& data-rawheight=&422& class=&origin_image zh-lightbox-thumb& width=&2217& data-original=&https://pic4.zhimg.com/b1e8d8b998ff470e3b998d_r.jpg&&&/figure&&br&&p&对于SerializedFile,则是当你使用LoadFromCacheOrDownload、CreateFromFile或new WWW本地AssetBundle文件时产生的序列化文件。&/p&&p&对于WebStream和SerializedFile,你需要关注以下两点:&/p&&blockquote&&ul&&li&是否存在AssetBundle没有被清理干净的情况。开发团队可以通过Unity Profiler直接查看其使用具体的使用情况,并确定Take Sample时AssetBundle的存在是否合理;&/li&&li&对于占用WebStream较大的AssetBundle文件(如UI Atlas相关的AssetBundle文件等),建议使用LoadFromCacheOrDownLoad或CreateFromFile来进行替换,即将解压后的AssetBundle数据存储于本地Cache中进行使用。这种做法非常适合于内存特别吃紧的项目,即通过本地的磁盘空间来换取内存空间。&/li&&/ul&&br&&p&&strong&注意:关于AssetBundle的详细管理机制,建议查看我们之前的&a href=&http://link.zhihu.com/?target=http%3A//blog.uwa4d.com/archives/ABTheory.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&AssetBundle技术文章&/a&。&/strong&&/p&&/blockquote&&h1&&strong&托管堆内存占用&/strong&&/h1&&p&对于目前绝大多数基于Unity引擎开发的项目而言,其托管堆内存是由Mono分配和管理的。“托管” 的本意是Mono可以自动地改变堆的大小来适应你所需要的内存,并且适时地调用垃圾回收(Garbage Collection)操作来释放已经不需要的内存,从而降低开发人员在代码内存管理方面的门槛。&/p&&p&&strong&但是这并不意味着研发团队可以在代码中肆无忌惮地开辟托管堆内存,因为目前Unity所使用的Mono版本存在一个很严重的问题,即:Mono的堆内存一旦分配,就不会返还给系统。这意味着Mono的堆内存是只升不降的。&/strong&举个例子,项目运行时,在场景A中开辟了60MB的托管堆内存,而到下一场景B时,只需要使用20MB的托管堆内存,那么Mono中将会存在40MB空闲的堆内存,且不会返还给系统。这是我们非常不愿意看到的现象,因为对于游戏(特别是移动游戏)来说,内存的占用可谓是寸土寸金的,让Mono毫无必要地锁住大量的内存,是一件非常浪费的事情。&strong&所以,我们在UWA测评报告中,为研发团队统计了测试过程中累积的函数堆内存分配量,大家只需要通过查看堆内存分配Top10的函数,即可快速对其底层代码实现进行查看,定位是否有分配不必要堆内存的代码存在。&/strong&&/p&&figure&&img src=&https://pic1.zhimg.com/2b1af9fa87f7cd7b9e60bea_b.jpg& data-rawwidth=&2346& data-rawheight=&897& class=&origin_image zh-lightbox-thumb& width=&2346& data-original=&https://pic1.zhimg.com/2b1af9fa87f7cd7b9e60bea_r.jpg&&&/figure&&br&&p&读到这里,你可能会产生这样的疑问:&strong&我知道了哪些函数的堆内存分配大了,但是我该如何去进一步定位不必要的堆内存呢?&/strong&&/p&&p&这是我们经常遇到的问题,所以在我们的深度项目优化服务中,我们都会直接进驻到项目团队,现场查看项目代码并对问题代码进行定位。在经过了大量的深度检测后,我们发现用户不必要的堆内存分配主要来自于以下几个方面:&/p&&blockquote&&ul&&li&高频率地 New Class/Container/Array等。&strong&研发团队切记不要在Update、FixUpdate或较高调用频率的函数中开辟堆内存,这会对你的项目内存和性能均造成非常大的伤害。&/strong&做个简单的计算,假设你的项目中某一函数每一帧只分配100B的堆内存,帧率是1秒30帧,那么1秒钟游戏的堆内存分配则是3KB,1分钟的堆内存分配就是180KB,10分钟后就已经分配了1.8MB。如果你有10个这样的函数,那么10分钟后,堆内存的分配就是18MB,这期间,它可能会造成Mono的堆内存峰值升高,同时又可能引起了多次GC的调用。在我们的测评项目中,一个函数在10分钟内分配上百MB的情况比比皆是,有时候甚至会分配上GB的堆内存。&/li&&li&Log输出。我们发现在大量的项目中,仍然存在大量Log输出的情况。建议研发团队对自身Log的输出进行严格的控制,仅保留关键Log,以避免不必要的堆内存分配。&strong&对此,我们在UWA测评报告中对Log的输出进行了详细的检测,不仅提供详细的性能开销,同时占用Log输出的调用路径。这样,研发团队可直接通过报告定位和控制Log的输出。&/strong&&/li&&figure&&img src=&https://pic4.zhimg.com/c733c06e105aec4a1c93_b.jpg& data-rawwidth=&2279& data-rawheight=&1183& class=&origin_image zh-lightbox-thumb& width=&2279& data-original=&https://pic4.zhimg.com/c733c06e105aec4a1c93_r.jpg&&&/figure&&br&&/ul&&br&&ul&&li&UIPanel.LateUpdate。这是NGUI中CPU和堆内存开销最大的函数。它本身只是一个函数,但NGUI的大量使用使它逐渐成为了一个不可忽视规则。该函数的堆内存分配和自身CPU开销,其根源上是一致的,即是由UI网格的重建造成。因此,其对应的优化方法是直接查看&a href=&http://link.zhihu.com/?target=http%3A//blog.uwa4d.com/archives/optimzation_cpu.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&CPU篇&/a&中的UI模块讲解。&/li&&figure&&img src=&https://pic2.zhimg.com/4b81de8754fef9b3974224abea3e44b4_b.jpg& data-rawwidth=&2293& data-rawheight=&893& class=&origin_image zh-lightbox-thumb& width=&2293& data-original=&https://pic2.zhimg.com/4b81de8754fef9b3974224abea3e44b4_r.jpg&&&/figure&&br&&/ul&&/blockquote&&p&关于代码堆内存分配的注意点还有很多,比如String连接、部分引擎API(GetComponent)的使用等等,这些已经是老生常谈了,鉴于篇幅限制不在此处多作介绍,大家感兴趣可以Google自行搜索。后续也会有专门的代码效率专题讲解,敬请关注。&/p&&h1&&strong&UWA测评的内存标准&/strong&&/h1&&p&在大家使用过UWA之后,对于UWA推荐的内存标准值提出了很大的疑惑。在这里,我们也分享下UWA内存标准的制定规则。&/p&&p&(1)150MB的总体内存标准主要由以下两个因素得出:&/p&&blockquote&&ul&&li&&strong&经过了大量的项目优化后总结而得。&/strong&其实,对于目前市场主流的Unity游戏来说,其内存占用主要集中在120~200MB。同时,顾及到iPhone4和512MB/768MB等低端Android机型,其应用的自身总体内存占用不可超过200MB(iPhone4的安全线应该在180MB左右),所以我们将Reserved Total设定在150MB,这是Unity引擎的自身内存分配,以保证App在使用到的系统库后,其OS中的整体内存也在200MB以下。&/li&&li&&strong&某些渠道对Android游戏的PSS内存进行了严格的限制。&/strong&一般要求游戏的PSS内存在200MB以下。这是我们将Reserved Total内存设定在150MB的另外一个重要原因。&/li&&/ul&&/blockquote&&p&(2)当总体内存设定为150MB后,我们进一步对其具体分配进行了设定。但需要说明的是,这里的内存分配其实并没有严格的公式来进行论证,仅是我们在大量的项目优化工作中提炼出的经验值。目前,项目较为合理的内存分配如下:&/p&&blockquote&&ul&&li&纹理资源: 50 MB&/li&&li&网格资源: 20 MB&/li&&li&动画片段: 15 MB&/li&&li&音频片段: 15 MB&/li&&li&Mono堆内存: 40 MB&/li&&li&其他: 10 MB&/li&&/ul&&br&&p&需要指出的是,150MB中并没有涵盖较为复杂的字体文件(比如微软雅黑)以及Text Asset,这些需要根据游戏需求而定。&/p&&/blockquote&&p&(3)目前的UWA内存标准是较为苛刻的,对于中高端设备而言,其内容允许量其实要比150MB要大得多。但我们坚持认为,在研发过程中,一个严苛的标准对于一个项目来说是一件好事。至少,它可以为大家提个醒,让大家时刻关注自己的问题。据我们了解,目前的三到五线城市,其低端手机的覆盖率还是相当高的。同时,对于中高端移动设备,我们仍在不断试验和研究中。我们希望在不久的将来可以做到针对各种不同档次的机型都给出一个更为合理的推荐值,从而让大家更为简单地对内存进行管理。&/p&&p&以上所说的是游戏项目中主要的内存分配情况,希望读到此处的你,可以更加了解Unity项目的内存开销和潜在问题,并对自己的项目进行更有针对性的检测。&/p&&p&除以上内容外,还有两个更为重要的地方需要研发团队关注:&strong&内存泄露&/strong&和&strong&资源冗余&/strong&。我们将在下一篇内存优化文章中为您带来相关分享。同时,不同的项目遇到的问题不尽相同,欢迎大家加入到UWA的产品QQ群(),就相关内容来进一步讨论。&/p&
项目的性能优化主要围绕CPU、GPU和内存三大方面进行。接上期专讲,我们本期和大家分享内存方面的优化心得。无论是游戏还是VR应用,内存管理都是其研发阶段的重中之重。然而,在我们测评过的大量项目中,90%以上的项目都存在不同程度的内存使用问题。…
今天做阶段性总结,按自己的经历整理了客户端开发知识体系,一切理解都是个人的理解,仅具备参考性和了解性!&br&&br&嫌图片看的不过瘾,就去百度脑图看:&a href=&//link.zhihu.com/?target=http%3A//naotu.baidu.com/file/0f5a2aac98ecd93face3023%3Ftoken%3De0cef00& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&百度脑图-便捷的思维工具&/a&&br&&u&&b&添加了一个“其他”分支。&/b&&/u&&figure&&img src=&https://pic3.zhimg.com/cafb5c120396_b.png& data-rawwidth=&1146& data-rawheight=&2117& class=&origin_image zh-lightbox-thumb& width=&1146& data-original=&https://pic3.zhimg.com/cafb5c120396_r.png&&&/figure&&br&写了很久,最后当然是求个赞~~???(?σ????? ?σ????)·??
今天做阶段性总结,按自己的经历整理了客户端开发知识体系,一切理解都是个人的理解,仅具备参考性和了解性! 嫌图片看的不过瘾,就去百度脑图看: 添加了一个“其他”分支。 写了很久,最后当然是求个赞~~???(?σ?…
&figure&&img src=&https://pic2.zhimg.com/v2-89ed7cc78c1f13cc87c9_b.jpg& data-rawwidth=&1280& data-rawheight=&854& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic2.zhimg.com/v2-89ed7cc78c1f13cc87c9_r.jpg&&&/figure&&p&&b&主题:&/b&&/p&
&p&技能系统是游戏中非常重要的组成部分,因为它不仅需要实现,技能从触发、释放到伤害,还紧密涉及游戏逻辑——这个游戏怎么玩,本文会简单给出技能系统的设计方法,和代码流程框架。&/p&
&p&&b&注意:&/b&&/p&
&p&1. 不会贴代码,我认为理解思路后用自己的方式实现很重要。&/p&
&p&2.&b&&u&本文仅仅抛砖引玉&/u&&/b&。&/p&
&h2&一 思考如何设计技能系统&/h2&
&p&首先给出我思考的结果,就是下图,看完这幅图后,我再来解释为什么这么设计。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-7aacad58ce1c8ca7753bf_b.jpg& data-rawwidth=&1141& data-rawheight=&706& class=&origin_image zh-lightbox-thumb& width=&1141& data-original=&https://pic1.zhimg.com/v2-7aacad58ce1c8ca7753bf_r.jpg&&&/figure&&p&解释部分:&/p&&p&1. 为什么我要先定义“角色”?&/p&&p&“角色”是游戏的承载对象,如果不先从具体的行为中抽象出它的功能,在写代码的时候有可能会无法确认这个功能是不是该放到角色身上。&/p&&p&2. 图中没有给出角色的分类,只有角色的功能分析,这里我补充一下,其实很简单:角色分为用户和AI,用户分为自己和其他玩家。&/p&&p&3. 交互行为的分法和主体并不一样,这里提示,对每个大类的分法并不固定,分的原则遵循——各部分之间相互独立,相互排斥,没有重叠;所有部分完全穷尽,没有遗漏。&/p&&p&4. 后面的分支我就不一一赘述为什么要这么分,因为这里用的就是经验和实际用途了。&/p&&p&5.
解释下两种主体数据,游戏属性和功能属性:&/p&&p&游戏属性:理解为非游戏逻辑相关的,如animator里的各种参数。&/p&&p&功能属性:游戏逻辑相关,如判断人物是否处于释放技能状态。&/p&&br&&h2&二 设计代码框架&/h2&&p&1. 代码执行流程&/p&&figure&&img src=&https://pic2.zhimg.com/v2-fcf038a26df064d64f392fa_b.jpg& data-rawwidth=&1066& data-rawheight=&425& class=&origin_image zh-lightbox-thumb& width=&1066& data-original=&https://pic2.zhimg.com/v2-fcf038a26df064d64f392fa_r.jpg&&&/figure&&p&2. 解释流程&/p&&p&1) RoleSkillController是每个角色的技能控制中心,它接受用户点击控制,或AI控制,传进来skillId后,根据skillId知道技能类型,创建或初始化对应的RoleSkill(基类为RoleSkill),同时通知StateMachine切换状态,StateMachine切换到skillState后,角色不是立即就碰撞检测了,因为技能动作还包括准备动作,必须等到动作打出去了,再告诉RoleSkill你可以碰撞检测了。&/p&&p&2) 怎么对技能分类?&/p&&p&我的分法是,所有技能的基类是RoleSkill,然后分近战和远程两个大类,记得不要根据职业来分,而是根据功能来抽象,近战的技能是通过武器来产生伤害,而远程技能是通过发射物来伤害。近战技能可以继续分为:近距离接触攻击单人,近距离范围内接触攻击多人等;远程技能可以分为:单发射物攻击单人,远距离范围内非接触攻击多人等。&/p&&p&3) 如何对导入的动作做修改,插入事件,最后用代码捕获事件?&/p&&p&&u&对导入动作做修改看这个视频:&/u&&/p&&p&&a href=&https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DcNnnaHqhks0%26t%3D3s& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&youtube.com/watch?&/span&&span class=&invisible&&v=cNnnaHqhks0&t=3s&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&&u&插入事件有两种方法&/u&,一种是用Animation面板来做;另一种是在动作面板里修改,如下图&/p&&figure&&img src=&https://pic3.zhimg.com/v2-2e2e3d5f47c3c6c55ca349_b.jpg& data-rawwidth=&372& data-rawheight=&644& class=&content_image& width=&372&&&/figure&&p&&u&捕获事件&/u&,代码一定放到和Animator平行的地方,如下图,代码事件名和面板里的保持一致:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-d8e917acd307ed34fd546d8_b.jpg& data-rawwidth=&373& data-rawheight=&328& class=&content_image& width=&373&&&/figure&&p&3. 知道代码流程框架,根据设计图明白功能规划,我觉得差不多就可以做出自己的技能系统了。&/p&&p&&b&后记:&/b&&/p&&p&1. 我知道看起来很容易,但就是写不出来的感觉是什么样的,放心~光那个技能设计图的实现我就写了四遍,实现了那么多遍后,我才知道哪种写法是简单有效的。&/p&&p&2. 看了那么多设计模式,不如通过实践知道两个简单的设计原则,一个是奥卡姆剃刀原则:如非必要勿增实体;另一个是所有复杂的系统都是由极其简单的系统组合而来,当你的系统特别复杂,不知如何下手时,试试把它们拆解为原子系统(不可再分系统),了解情况关系再来设计。&/p&&p&
3. 简单即是美。&/p&
技能系统是游戏中非常重要的组成部分,因为它不仅需要实现,技能从触发、释放到伤害,还紧密涉及游戏逻辑——这个游戏怎么玩,本文会简单给出技能系统的设计方法,和代码流程框架。
1. 不会贴代码,我认为理解思路后用自己的方式实现很重…
&figure&&img src=&https://pic1.zhimg.com/87cdc84ebb9_b.jpg& data-rawwidth=&378& data-rawheight=&209& class=&content_image& width=&378&&&/figure&&p&本文由腾讯WeTest授权发布 &br&作者:chunhe,腾讯资深后台开发工程师。 &br&链接:&a href=&http://link.zhihu.com/?target=http%3A//wetest.qq.com/lab/view/108.html%3Ffrom%3Dcontent_zhihu& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&http://wetest.qq.com/lab/view/108.html&/a&&br&著作权归作者所有。商业转载请联系WeTest获得授权,非商业转载请注明出处。&/p&&p&俗话说,用户体验不谈性能就是耍流氓。 在PC游戏上的性能问题并没有那么明显,加个内存换个CPU或者刷个主频就能轻松搞定;到了手游时代后情况则显得比较严峻,捉襟见肘的内存使得资源加载时如履薄冰,加上高中低不同配置的机型让性能问题显得更加突出,一个低端机型上的卡顿就可能造成一大批屌丝用户的流失,这当然无法被忽视。&/p&&p&在手游的浪潮之巅,腾讯对于手游品质的要求从1.0到2.0再到现在的3.0,不仅是玩法和内容,在游戏质量的审核上也始终如一的保持着高要求高标准。腾讯游戏的品质管理中心在Unity手游性能上进行了更深层次的挖掘,这是一个腾讯内部非常受欢迎的性能分析产品,无论你是否正在从事Unity相关的工作,听完这个良心产品的故事保证会让你增加90%的魅力值。但在此之前、先要看看你的“性”能到底行不行?&/p&&p&(下文有大量专业术语,有可能引起您的不适,请在家长指导下阅读。)&/p&&p&一.常见的Unity手游性能问题有哪些?&/p&&p&Unity手游的性能问题一直是被业内视为诟病,腾讯公司内部的TDR评审就是一个专门针对技术细节进行专家团评估的环节;早期的TDR评审关注的是内存是否超标、CPU是否饱和、网络流量是否过大等数据,经过近几年手游浪潮的洗礼,现在评审过程中会更加注重细分问题的研究和排查。 &br&&/p&&figure&&img src=&https://pic4.zhimg.com/0d7ca6ebd2e5abfa36fbfe28_b.jpg& data-rawwidth=&630& data-rawheight=&472& class=&origin_image zh-lightbox-thumb& width=&630& data-original=&https://pic4.zhimg.com/0d7ca6ebd2e5abfa36fbfe28_r.jpg&&&/figure&&br&&p&如果说左边是玩家经常会遭遇到的表面现象,那右边则是基于Unity引擎深挖后的问题本质。 它们对游戏的具体影响是什么呢?就拿最近比较火的《王者荣耀》来举例,我们有幸参与了它上线前后的几个优化版本的分析,先后遇到过的问题和优化方法主要有下面几个: &br&&/p&&p&1.由于实时对战游戏的数据包数量巨大,早期版本的帧同步策略会导致比较明显的卡顿,通过进行数据包的合并与优化逐渐解决了卡顿问题; &br&2.频繁创建和销毁的小兵对象让CPU爆表了,大量的小兵如果采用实时内存的分配和回收,会产生大量的内存碎片和系统开销,解决方法之一就是采用高效的对象池进行优化,对每个内存对象的状态进行操作即可; &br&3.性能分析过程中,发现单人同屏和多人同屏时的开销都很大,通过视野裁剪技术,使得玩家视野外的不必要的特效和渲染可以全部关闭,极大降低了CPU、GPU和内存的开销; &br&4.在高中低三档机型上玩游戏时,分别加载不同层次的特效包,这也有助于降低CPU和内存的开销; &br&5.游戏内界面采用了UGUI的方式实现,但大量的实时UI变化使得副本内每帧会有230以上的drawcall,导致中低端机型感受到明显卡顿,最终采用UGUI+自研究UI的组合拳,重写了一套紧密结合游戏自身特性的UI来实现战斗血条和浮动文字的效果。&/p&&p&二.手游发布之前的性能分析&/p&&p&近年来,经过若干惨痛的教训之后,业内已经逐渐意识到手游性能已成为了生死存亡的关键,特别是对于做大DAU的手游来说尤为重要。腾讯对于手游性能的测试和监控也是多管齐下,在新版本发布之前会再三确认性能是否符合发布标准,拿王者荣耀这款实时竞技游戏来说,在测试阶段会采集大量的性能数据进行分析,测试经理对各项性能指标进行评估并给出最终质量结论。 &br&&/p&&figure&&img src=&https://pic4.zhimg.com/1915debcf79f6faf2309dd_b.jpg& data-rawwidth=&1085& data-rawheight=&348& class=&origin_image zh-lightbox-thumb& width=&1085& data-original=&https://pic4.zhimg.com/1915debcf79f6faf2309dd_r.jpg&&&/figure&&br&&p&如上图所示,首先,功能测试也就是通常所说的人肉测试,用于测试游戏的新、老功能点,测试工程师在工作过程中可以使用&a href=&http://link.zhihu.com/?target=http%3A//wetest.qq.com/cube%3Ffrom%3Dcontent_csdn& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Cube&/a&进行数据采集;自动化测试则是基于腾讯WeTestgautomator自动化框架来实现,功能类似于Robotium,在无须人力参与的情况下能覆盖到绝大部分技能、角色和关卡;灰度发布指的是在一个很小范围定点推送手游的新版本,并观察运营期的质量情况和玩家反馈。无论是哪种测试方法,在过程中都可以用&a href=&http://link.zhihu.com/?target=http%3A//wetest.qq.com/cube%3Ffrom%3Dcontent_csdn& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Cube&/a&进行数据采集,在测试完成后,服务器会自动进行数据分析并给出多项性能数据结论;这些性能数据的结论来自于Unity官方的推荐标准值和腾讯游戏海量的经验库,如果同意机器给出的结论则可以巩固当前算法,当然也可以挑战自动分析的结论,帮助后台改进算法,最终版本质量结论还是来自于

我要回帖

更多关于 刺客信条起源1.05刷钱 的文章

 

随机推荐