« September 2014 | Main | November 2014 »

October 27, 2014

文明太空的评测

Sid Meier's Civilization: Beyond Earth ,中文社区翻译成 文明 太空。这个周末全部耗在这个游戏里了,steam 统计有 35 小时的记录时间。

鉴于 steam 上全是差评,而我觉得游戏还不错,值得一玩。所以动手写了篇好评,拉高评价吧。

steam 上评测链接在此 ,觉得有用点个赞 :) 。

下面转贴在 blog 上。


作为一个文明脑残粉, 很早就在 steam 上下单预购了。这次中国区居然是最早一批 unlock 的,发售之准时值得赞赏。入手后玩了一整天,睡了一觉好好回味了一下再回来写评测。

对于玩过历代文明(外加桌面游戏版)的玩家来说,此作绝对不可以放过。不要扯什么文明 V 的引擎,把 DLC 做正作来卖什么的。 关键是游戏有没有新鲜东西可以玩,图形引擎神马的都是浮云。再说了,图形引擎绝对是有所改进的,增加了同步轨道卫星层,地图更立体了。 用户界面的易用性也得到了很大的改良,看着舒服一些,操作更顺手了。

如果你好 4X 类型游戏,这次绝对满足你。科技树更复杂,已经不是树了,变成了科技网,在每个节点上还分了主干科技和分支。根据三大发展方向,要做更多取舍。 所以发展更多样。游戏过程中还会有很多事件任务,根据你的发展方向让你作出不同选择让建筑效果不同。

地图探索也变得更有挑战。主要是地图上有了瘴气。人类路过会掉血,而异型在里面会回血,通过轨道卫星可以去处瘴气。这样你在探索的时候就需要更多策略选择。

土著异型打起来更难,攻城虫在初期除了用主城炮可以轰死外,那点部队围上去就是被秒的份。而且光打异型 AI 还会谴责你。同时也有很多科技可以回避和它们的直接冲突。

这个版本的文明,一场战役下来依然需要很长时间,甚至比文明五更长。所以在玩熟之前,做好一整天只能玩一盘的准备。用默认的快速小型,水星计划难度, 差不多需要接近 400 回合才能胜利。胜利条件很多,在熟悉系统的阶段,我选择的纯正路线,胜利条件应许之地。完成胜利条件需要三个阶段,可以按向导一步步来。 (不像以前文明那种单一目标)后期的回合等待时间很长,差不多要半分钟。不过因为整个游戏难度选择的不高,玩成倒不是难,后面就是等 AI 行动了。

接下来再挑战高难度,看看有什么新的有趣的东西可以写。


玩了 30+ 小时后的补充总结:

把系统熟悉后,你就可以随意玩了。本作难度不算高,我用最高难度(阿波罗计划)花了一整天时间,280 回合和谐超越胜利。原本以为回比较难,所以前 150 回合玩得非常小心。后来玩顺了觉得 AI 基本没可能竞争的赢,随便玩玩就够了。顺带摸索一下游戏里的各种系统。

对比之前用纯正应许之地胜利过两盘,发展路线还是有所区别的。和谐路线后面可以放瘴气加成。但是,如果地图上瘴气密集的话,游戏初期还是要把关键点的瘴气去掉好开商路。即使用和谐,纯正的第一点还是要加上避免探索者在野外被袭击。

下个周末可以考虑试一下至高,我相信还会有一些新鲜点。

总的感觉是和文明 V 做出了一些区别,不同的发展路线区别更明显。科技网上很多科技多半不用在同一局游戏里点出来。

野蛮人/异族的关系也并非完全敌对。如果你相处的好(游戏中可以发展出科技避免和它们直接冲突),甚至可以帮你制造出和 AI 势力的屏障。

印象比较深刻的是地形地貌系统更复杂一些,系统生成的地图也更有设计感。往往巧妙的利用地形,可以用很少的部队抵抗强大的敌人。而轨道层卫星的设计也让战略更立体化。即使是种田,你也用得上很多不同的轨道卫星。比如用相位传送卫星传送地球难民效率要高得多。

选择不同的星球带来的游戏感也不同。类地球的图和充满瘴气的图玩起来就很不一样。有的图更容易 AI 间内战,有的图则更偏向于协作。所以这版游戏够玩好几遍的了。

游戏的节奏感不错,比文明 V 要紧凑。宗教系统没有了,加强的间谍系统要有趣一些。胜利路线更加明确,这些系统都是围绕胜利路线进行的,不至于在玩的时候太茫然,不知道要发展什么好。而且只需要生产和控制不太多的单位就够了。这使得微操变得可能,而不用把大量的单位都选成自动操作。

再说点不好的地方:

难度还是偏低。你可以只使用很简单的策略就可以完成游戏,空有复杂的系统而无对手供挑战。恐怕必须等 DLC 出几版才有更多玩点。没试过多人游戏,如果有人可以陪我玩那是最好。但是鉴于单人游戏时间就够长了,没胆量尝试多人线上版本。

后期单回合等待依旧太长了,这是文明系统的通病。 200 回合后,时间基本花在在等 AI 行动上的。如果势均力敌还好,若是一边倒就是垃圾时间了。

鉴于 steam 上英文评测一边倒的差评,我就不吐槽 UI 、图像、以及一些游戏系统设计的细节了,挑剔的玩家在买之前可以读一下那些差评做参考。而我个人感觉是虽然有改进空间,但其实都还不算糟糕。


购买建议:

如果是文明新手,不是急着想尝试新系统的话,我个人建议购买带全套 DLC 的文明 V 完整版。你可以从剧情任务入手文明系列。否则一上来就是庞大的系统,大部分人会懵的。一旦你爱上文明,那么迟早你会回来尝试这个版本的。还可以等 DLC 出一些,随便来个打折。

如果你是科幻迷,那么这款游戏不可错过。只需要一点点耐心,就能带入到游戏中去。文明百科也值得阅读,文案写的相当不错。中文翻译质量也很高。

喜爱 4X 类游戏的玩家,若是最近没有别的选择的话,那么花上 50 刀可以玩上 50 小时,已经是非常值了。

October 23, 2014

GDC China 2014

上周末去上海参加了 GDC China ,没有演讲,被邀请是因为要给 IGF 颁奖。对会议没有什么期待,所以有所收获也是超出期望的。

在国内做商业化游戏这么多年,身不由己去为许多并不喜欢的游戏元素花心思,对纯粹的游戏制作还是很向往的。希望在公司有稳定的收入之后, 可以能专心考虑为核心向玩家多做一点东西吧,至少不用整天想怎么伺候好大 R 。不用想这个玩法是不是太复杂了,没有多少人会接受,接受后也多花不了几块钱。 多花一点精力在如何让玩家在游戏过程中更多的感受到游戏带给他的乐趣上。

IGF 的颁奖晚会挺让人激动的。在拆开信封之前,我也不知道里面写的是哪款游戏。很遗憾我所喜爱的 Sumoman 没能获奖。据说它获得了许多评委的提名,但由于提名过于分散在不同的奖项上,最终一个奖都没有拿到。 原本我觉得至少得个最佳音乐音效奖的。如果你能观看 youtube 的视频,可以看看这款游戏 的制作花絮。

僵尸别动队 获得最佳移动游戏奖有点小意外,相信对开发团队也是个意外之喜。主创陶文在讲台上都激动的语无伦次了,用中文英文日文各表达了一次自己对游戏的热爱。 我能深深体会他们制作独立游戏的不易,能把项目完成经历了太多磨难。希望这次的奖项能给他们带来点好运气。


周一下午参加纪念碑谷的圆桌讨论。我提前到了会场,Ken Wong 刚好也在外面。之前我们并不相识,但有一些共同的朋友。虽然我英文表达很糟糕,他的中文说的也不太好,我们还是聊了几句。 他问了一个问题,在国内,能做出纪念碑谷这样的游戏么?我不知道怎么回答。简单说呢,是因为钱(我的英文表达能力也仅限于此了),所以很难有公司去用心做这样的项目。但似乎又不完全因为钱。

我们真的拿不出他们那样,10 个人 8 个月的时间去打磨一款这样的游戏吗?或是创意真的这么难么?我看都不是。


课程我这次大概听了 4,5 个。

周日的关卡设计的教程很有趣。由于我到会场比较晚,只完整听了最后两个章节。主要是针对关卡的节奏控制的。(btw, 传统的游戏中,关卡设计师是一个很重要的职位,遗憾的是到了网游年代,大家都不这么去分工了,而变成了系统策划、数值策划这种奇怪的类别。)设计师需要针对游戏类型本身,先为游戏的设计要素归纳出一些元语(也可以算是模式吧),然后用这些元语把关卡组合起来。

每种模式对玩家的影响是不同的,在这样一个抽象层面组合这些元语,可以更方便的控制游戏的节奏。

比如在教程中用到的例子 half life 2 。每一个关卡都是由 5 种模式构成:分别是:战斗、过场、谜题、探索、远景。这些不是生硬的拼接在一起,而是在玩家游戏过程中平滑的切换的。不同的模式给玩家的感受是不同的,同一模式下进行太久都可能让玩家厌倦,或是过于紧张而疲惫。听课程的时候,我想到我们在斗罗大陆的制作过程中就在关卡设计中犯过很多错误:我们在游戏中制作了一些单人游戏的副本,希望把游戏性做得更好,但始终没做出满意的感觉。

整个课程是用英文讲的,结合幻灯片大致听得明白。配备了中文翻译感觉有点画蛇添足。台上每句英文之后,都会接下来在台下有中文翻译。且不说有些翻译用词不准确,关键是大脑不停的在听英文和听中文之间切换实在是受不了。

如果接下来这些教程有视频可以看,剪辑一下应该还值得再看一遍的。


突然想起来,第一次参加 GDC 是 2004 年的事情了,整整过了 10 年。把 10 年前写的文字抄在下面吧,算是一个纪念:

GDC 2004 见闻录 (2004 年 3 月 30 日)

老早就决定今年去GDC看看, 游戏开发者的盛会啊. 去美国的签证不好拿, 2 月被拒了一次.3月18日再去才拿到 visa. 同去的一个同事再次被拒了 :(

3月21日,经道香港乘新航的航班飞旧金山. 上次去澳洲坐的南航, 一对比, 发现南航真是垃圾啊,这次飞机上可以点播电影,音乐,打游戏, 吃的两餐都非常的好. 不过 12 小时的长途飞行,真的是很累.

到了机场, 由同事带着租了车驾车去 San Jose, 很快就到了. 短短 40 分钟的车程, 居然在 San Jose也发现了个国际机场 (._.!) 我们就在机场附近的一个很不错的 hotel 住下. 第一天晚上是最难受的,jet lag 很严重. 躺下来还是不舒服. 晚上 2 点醒来怎么都睡不着. 只到 7 点才迷迷糊糊睡过去,9 点爬起来去会场注册, 听教学讲座.

前两天的活动都是在 Convention Center, 会场的大厅可以免费接入无线网, 美国有一点很方便,就是在公共场所,随处可以看见插座. 根本不用担心笔记本没有电的问题. 可惜我没有带笔记本,只能用 PDA 看一些很简单的网页和收发 email. 当然, 活动安排的比较紧, 对于一千多刀的giga pass,只是在这里上网真是浪费. 早餐是随意拿着吃的, 倒了杯咖啡就去了一开始想去听的一个讲游戏平衡的讲座.

头两天是这样的, 都是全天的教学讲座. 每天都有十多个题目可以选, 分别属于 Audio, Visual Arts,Business & Legal, IGDA, Production, General Interest, Programming 几个类别的. 不过每个都是会讲一整天. 中间有两次 coffee break 和一个 Lunch 时间. 听英文真的很累. 加上时差问题, 周一和周二都很疲劳. 第2天由 XBox 组的人讲游戏的自动化测试给了我一些启发. 以后自己的游戏开发中应该多尝试用一下.

中午休息的时候看见过道上, 大厅的地板, 沙发上都坐满了人, 真是羡慕他们可以用英文自由的交流,我想以后在中国办一个类似的活动, 也能有上千游戏人聚在一起交流就好了.

大厅里还有很多游戏设计相关的书卖, 我翻了一下却兴趣不大, 英文的毕竟很头痛, 而且买下来搬回国也是件很痛苦的事情.

后三天, 人明显的多了起来, 因为后三天的票比较便宜, 而且活动也更多. 活动场所扩大到旁边的两个 hotel,和对面的一个剧院. 剧院主要是给名人演讲用的, 比如游戏界的 hero, John Carmake 在周四中午的演讲,大部分人都是慕名而去, 只是瞻仰下名人的 :) 这种演讲没有 ppt, 于我这样英文很糟糕的人来说,能听明白 30% 就不错了. 这几天我的收获却不小, 主要都是听的 Game Design 方面的.比如一个任天堂的日本人讲的 Risk and Return, 就非常的不错. 我给他打了 5 分. (每个 session 进场的时候都会发一个调查表, 离场的时候需要填写交回, 就是写上你对此的综合评分, 对演讲人的评分,对话题的评分, ppt 的评分等等等等) 他是用日语讲的, 同声传译的效果很好, 比那些带口音的老美强的多:)南梦宫的 pak-man 的作者, 那个幽默的老头在谈 pak-man 的哪个游戏点是这个游戏最成功时狡猾的说,因为 pak-man 里已经不能加如任何一个玩点, 也不能删除一个玩点, 所以游戏就成功了. 看的出来,他十分鄙视现在复杂的游戏, 说那些只是给很多年游戏经验的资深玩家设计的, 我们似乎已经偏离了游戏设计之道. 另外有个英国的老头谈当今的游戏设计也有类似的观点. 在鄙视了 doom 的故事情节,和黑客帝国的电影后, 提到, 听说 PS3 的多边形处理能力比 PS2 强了 1000 倍, 那是否意味着我们的游戏性提高 1000 倍呢? 听着这些技术指标, 就好比几百年前, 蒸气机刚发明时,有个蒸气机制造厂家宣布将发布一款气压超过原始设计 1000 倍的新机器, 同时宣布人们的生活质量将提高 1000 倍一样的荒谬,偏激的老头的话语多少还是有些能让人思考的东西.

程序方面的东西听的不多, 一个讲游戏里的多线程的, 和另一个基于行为编程取代有限状态机的 session,因为我做过相关的研究, 所以兴趣也比较大.而赞助商举办的 session, 多是宣传他们自己的技术, 本来我兴趣不大, 只是周五去听了个 intel 关于现代处理器如何提高 3d 方面的效率的, 在 Q&A 部分, 发现演讲人非常之牛, 在代码优化方面的造诣不是一般的深, 许多问题都是信手拈来. 离场后才注意到, 那就是大名鼎鼎的 Michael Abrash,让我差点认为那种近似变态的牛人, 在美国满大街都是了 :)另一个话题 Common C++ Performance Mistakes in Games 听者甚众, 想必演讲人也不是泛泛之辈.他在一开始就用非常幽默的语言表达了 STL is evil, 当然后来又加了一句 sometimes. 本来我对 STL 的效率非常的满意的, 听了开头还有一点点反感. 后来听到他强烈鄙视那些,自己去实现 STL 相关的功能, 仅仅是因为自己会做的人后, 不由自主跟着听众哈哈大笑.他讲了很多 C++ 的需要注意的小地方. 有那么几个居然是我自己也被忽视过的.也是有一些为我不赞同,当然还是由于我糟糕的英语, 没有和他在 Q&A 时间讨论.

后三天的 session 节奏都比较快. 平均 1 小时一个. 同时开的 session 更多. 每个时段要从几十个里面挑一个,总觉得难以取舍. 除了一些 session, 还有很多 roundtable, 大家坐到一个小房间里, 有一个共同的话题,和一个主持人. 在主持人的协调下讨论. 我参加了一个关于 lua 的, 交到好几个朋友. 可惜我的英文表达能力实在是太糟糕了. 连自己都觉得难受 ;)

在大的展区有各种游戏机的展示, 也看到了很多找工作, 和工作找人的展位 :) 这里大家都很随便,没有拘束的逛来逛去, 交朋结友. 在展区旁的一个角落里有个小放映厅循环播放着游戏相关的 video,躺椅很舒服, 免费的爆米花我没有吃. 光想着占个位置休息了.

每天晚上都因为同事有一些安排, 我也不好个人行动, 所以很多晚上的活动都没有参加, 比如独立游戏人年度颁奖仪式和一些狂欢节目. 周五最后一天我已经非常的累了. 时差一直都没有倒过来.当天晚上就飞回国, 回程 14 小时. 长途飞机还是一如既往的让人难受.

看来明年还值得再去一次呢. San Jose 的阳光,天气, 真的不错. 我也喜欢那种没有高楼的城市.

October 09, 2014

skynet 服务的过载保护

最近我们的新游戏《天天来战》上了腾讯平台,由于瞬间用户量过大,发现了几个 bug。

这几个 bug 都是在最后一周赶进度时编写业务的同学写的太仓促,在一些处理请求的流水线上使用了时间复杂度 O(n) 以上的算法导致的问题。这些时间开销大的操作,虽然并不常见,但操作误放在了和用户登录相关的服务中,导致一旦阻塞,使得用户登录受到影响。

具体 bug 没什么好谈的,把业务拆分开,以及用 O(Log N) 或 O(1) 的算法重新实现后就好了。但发生 bug 后,skynet 的整体表现值得一提。

按原有的设计,skynet 可以视为一个简单的操作系统。每个服务都是这个系统中的进程。不相关的业务应该互不干扰(使用多核的硬件,核心越多,就可以表现的越好)。在这次事件中,的确也做到了受影响的部分(登录)处理能力不足,用户无法正常操作时;另一些做无关操作(副本游戏)的用户没有收到影响。但在服务过载后的恢复环节却做的不够。

由于 bug 的影响,有类消息的处理能力只有 20 次/s 左右。当需要处理的消息频率超过 20 次后(在线玩家超过 8000 人以后出现),该服务过载,导致整个系统处于半瘫痪状态。新用户无法正常进入,直到在线人数下降到 4000 人都没有好转。但已在玩游戏的用户没有受到影响,所以没有做任何处理。大约在 2 个多小时后,系统自己维护正常。这比预期时间要长得多。

这是上周遇到的问题。昨天又在新一轮导量中出现了类似的问题。由于配置问题把大量玩家(十万数量级)引到同一组服务器,导致该服务器几乎无法创建新角色,同时老玩家登录也无法获取自己的角色(因为和创建角色在同一服务内)。如果玩家有足够耐心,等待 10 分钟,还是可以正常进入游戏。这个状态在分流新用户后,得到了缓解。但服务器依然用了小时级的时间才自我恢复。经事后排查,同样是一处 bug 导致的性能问题,但自我恢复时间过长也值得关注。


在 skynet 框架的基础上做设计,需要积累经验。应该尽量去掉单一的热点。如果很多业务流程都经过同一个服务,那么这个服务的处理能力很容易就约束整个系统。

如果这种单点服务无法拆分,那么除了尽可能的优化它(以提高整体处理能力)之外,对其做过载保护也是很有必要的。

在上面的实例中,过载造成的雪崩是这样发生的:

有一个 skynet 内部服务 D ,它负责处理大量的数据。数据源来至于玩家客户端代理 agent 。每个玩家都在 skynet 系统中有一个 agent 服务做为状态维持的代理,而 D 并不维持状态,它仅处理 agent 发给它的请求。

注:这是一个明显的热点,D 的处理能力很容易影响整体的处理能力。我们应该对 D 做拆分,比如按业务拆分开,或按玩家 ID 拆分。但这不是本篇谈论的重点。

D 的处理能力有限,当请求过多时,每个请求都需要较长时间才能得到回应。这就是所谓的过载。过载发生一旦被感知,维护人员可以做的最快的应对策略是把用户分流,但为什么用户减少后,系统没有立刻恢复过来呢?

这是因为,过载发生的那段时间内,每个用户都在等待,而大部分用户又没有足够的耐心,他们选择了断开连接,重新登录再试。而 D 无法感知外部连接情况,它平等对待没有请求。结果在同一个用户的不断尝试中,待处理队列中堆积了大量的无效业务。直到业务处理完成要把结果发回时才发现回应方已经不需要结果了。

这种情况一旦发生,有效处理能力进一步的减少,加剧了过载。即使屏蔽了新用户进入,依然在很长时间都得不到缓解。


我们可以用一个形象的比喻来描述这个问题。

有一家餐厅很大,可以坐很多桌人。这是当地唯一的一家餐厅,所有的饥肠辘辘的吃客都会拥进来坐满餐厅。

但餐厅的厨师有限,在客人很多的时候需要更多的时间做菜。每桌坐下来的客人都会把点单送入厨房,然后等待。尤其是客人点一些非常耗时的菜时,所有客人都等待更长时间。

有些没有耐心的客人会忍不住离开,但是厨师并不知道,他无暇分清做的菜是哪位客人的,只是按订单一盘盘做。等菜做好后为时已晚,客人已经走了,只好倒掉。

而这些离开的食客往往又耐不住饥肠辘辘返来,可按照规则,他们必须坐到新桌上重新点餐。缺乏有效的沟通,即使之前的点单还没开始做也不能取消。只好眼睁睁看着之前点的菜被端上来又倒掉,还得继续空等他们后来下的单。

这样,餐厅的接待能力进一步下降,使得平均等待时间更长,超过了更多的客人的耐心。最后,即使所有的客人最终都离开不再回来,厨房里依然需要忙碌很久,去做那些没有人需要的订单。新来的客人也必须等待很久才能进餐。


这种管理方案显得如此愚蠢,没有餐厅会这么干。但在我们的系统中,的确很容易犯这个错误。skynet 的服务只有消息接收队列,没有消息发送队列。无论对方接收队列多长,请求总是无条件的投递过去。即使发送者退出,也无法撤回未完成的请求。处理消息的一方,在处理消息时,做到感知请求方是否存在再决定是否真正处理消息会增加很大的设计复杂度,同时也可能影响性能。

我建议用一个简单的模式来解决这种过载之后的性能进一步恶化的问题:

对于这种热点服务,对于所有请求( 也只可以针对不能在 O(1) 时间处理的请求 )都在回应协议中增加一个 boolean ,表示服务繁忙。请求方必须处理这个繁忙标记。

服务提供方在收到每个请求时,先不急于处理,而是通过 skynet.mqlen 检查当前的消息队列长度,来判定是否繁忙。(一个小优化是,可以不用每个消息都取 mqlen 判定繁忙,而让繁忙标记在设置后维持连续几个消息。)如果繁忙,则直接扔掉请求,直接返回忙,直到消息队列被处理的差不多再做进一步处理。

而发送请求方则把 skynet.call 的调用改成一个循环。检查到忙,再接着重试,直到正确处理为止。做一个简单的封装后,可以看成和之前是一样的。

用前面那个餐厅的例子,现在变成了这样:

当空桌过多时,直接赶走新来的客人。一旦客人变少,就继续按原有的方案把客人的点餐单送入厨房。一部分饥肠辘辘的客人被赶走后会回来继续排队(这相当于那个循环尝试,重新发送请求需要一点时间)。另一部分没有耐心的客人选择暂时离开,等他饿坏了再来(相当于断开重连),也重新排到队尾。但和之前的方案不同的是,重新重新排队的人之前没有向厨房提交过订单。

当然,这个方案仅仅减少了浪费,让情况不至于恶化。多雇几个厨师,以及改进菜品的制作时间必须双管齐下。


对于没有 skynet 的开发经验的同学,第一次犯错简直是必然的。所以我最近的工作都是在加强 skynet 对于过载的预警。在目前的 dev 分支上,任何一个服务的消息接收队列过长(超过 1024)都会记录一条 log ;但并非所有过载都是体现在内部消息队列上的。比如一个对外部数据库对接的服务,过载会体现在外部数据库连接的发送队列过长 ,同时也反映在服务未完成的请求增加。所以,当一个服务的 coroutine 池的大小持续增加(每增加 1024 个)时,也会自动记录 log 。

可以利用 skynet 内部的 profile 统计单条请求的处理时间也非常重要。找到热点服务中的耗时请求,重点优化。