说说《三角战略》的投票系统

SE上个月发售了《Triangle Strategy》,这个游戏被我视作《皇家骑士团》的精神续作,自然是第一时间入手了。然而因为老头环的存在,没有第一时间开始投入的玩。直到白金了老头环之后我才捡起来。

打老头环的时候,和老婆一起断断续续玩到第七章,对剧情的感觉是还行,没有特别的逻辑崩坏,人物智商也都在线。没想到就从第七章开始悲剧了……

这游戏除去战略关卡,比较新鲜的就是投票系统了。具体来说,就是战略的下一步走向不是简单的由主角自己决定,而是要靠7位性格各异的伙伴投票。主角只能尝试说服他们,但对方不一定听主角的话。

第一次看到这个系统是在第3章,觉得很有意思。7这个数字不能被3整除,正好代表游戏标题的三种不同的价值观。2:2:2然后还有骑墙派,主角只需要说服骑墙派就可以左右信念的天枰。没想到开始投票才发现,方向只有2个。而且主角似乎很容易就把大家都说服了,全民投票通过,团结的不得了。

然后到了第7章,终于出现了稍微严肃一点的选择。这个时候违和感就出现了,因为我发现无论怎么S/L,7个小伙伴总有4个人投出和我想要的方向不一致的的结果。仔细研究了这个游戏的数值系统之后,我和老婆才发现这游戏并不是自由选择走向的游戏,而是个非常简单的二极管数值系统,并且参杂了策划自己的强制路线,顿时就让剧情选择的体验降成了0。

具体的吐槽我列这么几点,尽量不剧透,防止有玩家搜到这篇blog……

1、价值观投票完全由数值决定

本来游戏设计了三个不同的价值观,分为“自由Liberty”,“道德Morality”,还有“功利Utility”。从名称上来看,三角策略嘛,也就是三条路你自己选。当然,由于路线是同伴决定的,同伴的价值观实际上左右了投票的结果。

如果不被剧透,玩家会觉得自己可以自由的展现自己的价值观,然后导向不同的结局。如果同伴和自己产生分歧,只要尝试去说服即可。但这个说服系统居然不是按照收集的线索或者说服选项来定的,完全是按照“主角”自身的三项数值是否简单的满足策划设定的说服条件。

也就是说,如果主角的“道德”水平足够高,那么主角就可以说服一个“功利”的角色去做出“道德”的选择。这听起来就很不可思议了,为什么主角我自己道德水平高会影响功利角色的道德抉择呢?而且如果道德值不够,即使主角已经可以在逻辑上说服功利角色,“道德”选择是最有利的,功利角色自己也“陷入沉思”……最终投票的时候还是会义无反顾的投下功利票。

具体判断流程是,首先策划给每个角色安排一种投票方向,基本上3个人向左,3个人向右,1个人骑墙,实际骑墙角色也有策划固定的走向。接下来判断主角的三个隐藏价值观,小于被说服角色的“阈值”,直接显示“似乎有些冷淡”。这听起来有机会其实是中文翻译的太含蓄了,英文直接是“talking to a wall”,数值不够说啥都白瞎。数值够了的情况下,如果高出非常多,选啥都可以说服。如果不高不低,就看你选项有没有道理,有道理就成功说服了。

所以系统策划才是上帝,是策划写死的剧情走向,是策划设计了多周目数值继承。只要玩多周目,不管你的说服选项多么无厘头,只要积累的数值够高,总是可以说服各种价值观的角色同意自己的观点。知道这点之后,我和老婆就对游戏的“自由度”系统丧失了全部兴趣。

2、剧情对话是三元,但投票几乎都是二元

这个游戏设计了3个价值观对应的结局,无可厚非。但是还保留了隐藏结局,比普通结局多出好几章游戏内容。从剧情走向来看,大概作者自己想表达“共存”是可能的,三个价值观并非一条路走到黑,如果共存就能导向圆满的隐藏结局。

总结一下就是,想要达成圆满结局,当遇到关键的选择时,1个选择需要功利,1选择需要道德,1个选择需要自由。然而每次都是二元选择,其中一项数值无法发挥作用。

这个时候无力感就出现了,凭什么所有的选项都是合理的,探索也都是完成的,偏偏因为该项数值不够高就不能继续呢?策划按着玩家的头,让玩家吃屎。

3、都2222年了游戏还有死档

不得不说,剧本策划对自由派的心态拿捏还是比较准的。打到第7章,按照喜好选择的方向,基本都是朝着“自由”方向的抉择。单说这一点,我还是比较满意的。但是道德和功利的选项就很模糊,也可能是三观不合导致我不太能分辨。

然而到第7章出现的第一次投票,居然完全没有自由任何事情。其他两项数值非常低的主角就这样被锁死了选项,这条路线策划安排是“功利”,投票结果就是功利。所谓的自由度在这一刻碎成了渣渣,策划甚至不用特别麻烦的写剧情,只要操作骑墙派角色选择功利,就可以轻易导向功利的结果。

游戏不同于现实,在游戏玩家遇到两难选择的时候,因为游戏中的道德行为成本很低,大部分人应该是倾向于道德路线的。策划在这里强行喂屎,抛开剧情矛盾,自然会激起玩家的讨论。所以redit上充满了各种询问,究竟怎样S/L才能作道德选择呢?答案是你的存档已经被锁死了,想选就下周目吧。诛心的说,难道是为了话题性和营销,脸都不要了?

针对这一点,老婆表示,系统策划你已经失败了,想改进就等下辈子吧。

一开始就让玩家在三观上就有优劣之分,要么是做太多路线钱不够,要么就是剧本向着数值妥协了,总之这游戏给皇骑提鞋都不配,可惜了这套系统和美术。

这个SE的工作室的游戏都得拉黑了,制作人本质是个刷子爱好者,从《勇气默示录》到《八方旅人》,透露着一股所有东西都得给我刷级刷钱刷周目的设计让路的态度,残念啊……

Unity的美好与绝望

先说好的吧。可能目前最令我满意的就是IMGUI这部分API的定义,写Editor Plugin和In-game Debug Menu爽到飞起,很快就能出效果。

UI一向是很麻烦的东西,要保存状态,还要异步,还要同步View和Model的数据。很多框架动不动就是MVC,各种模式,用起来都痛苦的一比。这个IMGUI非常简单粗暴,反正也不能用来开发更复杂的玩意儿,设计和使用契合度非常高。

目前用到的其他特色的设计,比如Component Based,和别的商业引擎比起来大同小异。当然从价格和可用性的角度,Unity更胜一筹,以后有机会再多扯点。

主要还是吐槽,就说点看似美好其实比较坑的东西吧。

官方文档

全还是比较全的,这个我主要吐槽两点。

第一是组织方式,有些很重要的东西(比如对象的生命周期),或者说Unity和其他引擎比很不一样的东西(例如特殊目录,Editor/Resources/),隐藏在犄角旮旯等着你来发现。基本上都是在别处找到更直接的教程,然后拿到关键字,再到官方来看细节。

第二是官方真喜欢视频教程啊,不能搜还看得慢,动不动20分钟说点屁事。不能写点图文教程吗?比如IMGUI的各种用法,第三方写的比官方好用多了。

资源加载

三种方式,内在逻辑截然不同。

以Editor内操作为主,基于Reference的这套可能比较适合小游戏,或者非程序员开发的游戏。只要一切资源都是经过Editor操作和绑定的,那么后续过程也都是自动的。官方强力推荐这种,美术和策划友好的东西。

所有不能在Editor上绑定的数据,都需要Load-on-demand。一但牵扯到Load-on-demand,需要动态加载数据,事情就来了。

其实加载资源(Loading)是非常简单粗暴的操作。储存方面就是打个包,把数据和标识存起来。读取方面,只要给定一个标识(比如路径或者id),然后决定是同步加载还是异步即可。同步立刻返回结果,异步就给个handle或者允许callback。这样的底层设计几乎可以满足所有基本需求,其他花哨的玩意儿再上面继续包装即可。

但Unity的坑无处不在。首先是打包,Unity有两套截然不同的资源管理方式,分别对应Resources目录下的文件和Asset Bundle,姑且称为R和A。

R的打包是自动的,所有此目录下的文件都会在运行时打包,方便的很。这么好的东西,官方给出的Best Practice居然是“别用”。写文档的朋友,你以为自己很幽默吗?不能用的东西做出来吃屎呢……

A的打包是手动的,只不过没有现成UI可用,需要在Editor里调用API。但官方文档写的稀烂,打包和加载的过程同DLC的资料搅合在一起,还要牵扯到Cache和Server。乍一看仿佛要启动什么web service做host才能使用,打开还得从WWW下载。其实只要StreamingAssets目录一放,自己写脚本打包就好。

别忙,坑还没完。

R打包出来的资源是不带扩展名的,因为自动打包的时候就是根据扩展名来的,打好就全给删了。加载的时候遇到重名,请提供type。再出现重复我就不知道要怎么玩了……R的路径是相对于Resources的,这个倒还能理解。

A打包出来的资源,标识是写入的时候给定的数据,如果写的时候带了扩展,那就是有扩展名,目测不能重复。

所有“测试的时候想用R,发布的时候想用A”的同学,请自己写wrapper吧……真的好痛苦好痛苦。实际上更好的做法是,测试的时候直接读取Editor里面的AssetDatabase,并不需要使用Resources。官方说的“别用”就是字面意思,但您能提示下还有别的选择吗?直接介绍大家用AssetsBundle真的很不友好啊。

序列化和热更新 Hot-swapping

Unity一大特色就是各种自动,写个public直接就能在Editor上改了。而且改改c#,一回头自动把新的dll热更新上去,数据都还在。

听着很美好,实际情况是,改完代码出现大量Null Reference的异常……

https://gist.github.com/cobbpg/a74c8a5359554eb3daa5

这个小哥大概记录了一下,我踩了半天坑再补充一点:

1、首先是ISerializationCallbackReceiver,调用时机很诡异,Editor下如果你选中了带有这个接口的对象,Inspector会疯狂触发OnBeforeSerialize()。存起来很慢的东西就悲剧了。而OnAfterDeserialize()在Swap的时候会触发多次,目测Editor有创建多个实例,有些数据是没准备好的,还得自助检查。

2、在Editor里创建的各种引用,例如Component都会存下来。但如果动态AddComponent出来的玩意儿就悲剧了,在OnBeforeSerialize()之前就会被干掉,请自己重新动态创建。后来证明只要是Unity的Component,引用都会正确的保存下来,核心的混乱点还是Editor里有多个实例,初始化状态各不相同。

3、虽说需要动态创建,但特么的所有AddComponent这类方法,甚至GetTime都不允许在callback种调用。大概恢复数据的时候是多线程环境?所以只能自己搞个boolean做dirty check,然后在Update()里面实际恢复数据。实际上参考官方的例子,可以在OnEnable里面做恢复处理,比Update要省。

4、虽然官方号称大部分数据类型都可以自动保存,但“大部分”这种说法就意味着你需要被干很多次才能修复“少部分”的问题。比如标记为Serializable的数据,运行时可以为null,但Swap的时候会变成non-null状态。例如字符串变成了””,结构体变成了初始状态,最坑的是Array,里面的null元素会被填充。如果有逻辑依赖于null-check就悲剧了。

以后遇到新的再补充。

补充个新坑:打包的时候如果用BuildAssetBundleOptions.None这个option,看似人畜无害的默认选项居然是用LZMA压缩整个包,第一次开启会做解压缩操作,慢的一笔。最好的方式是使用ChunkBasedCompression,这个选项开包很快。港真我不知道None这个选项除了给网络下载几件衣服的DLC用以外还有什么应用场景,官方文档用这个名字(None是压缩的,咱还提供UncompressedAssetBundle选项哦~),并且用在代码范例真的好么?

2016迟来的忏悔

根本没有弃用任何SNS,有没有!!整一年,什么都没写。

2015超级超级忙,项目的事情就不多说了,都是辛酸泪。但Steam上总算搞出点花样,感觉不错。年底各种折腾装机,Linux,跨平台编译,树莓派等等,玩得杂,忘得快。

当然,这些内容我慢慢补。历年的传统,先谈谈玩了什么游戏。

去年爹妈来过年,帮我稍了块3DS烧录卡,于是乎终于可以玩跨区和汉化的游戏了。通关《勇气默示录》和《逆转裁判》之后,本以为《怪物猎人4》是中文版,有希望继续玩下去,但马赛克太重还是放弃了。妄我买了两份卡带和两份主机。

后来忙得只有碎片时间,就主要攻略炉石传说了。AAA当然不会错过,巫师3让我换了GTX960,然而并没有通关。尝试了Bioshock Infinite,也没有通关。但同样是突突突的Call of Duty-MW3就很快通关,可见5个小时才是最合适的游戏长度。

接下来在华丽丽的九月,各路大作隆重登场,然后我基本上就沉迷了。

首先一口气通关了合金装备3、4、5,还看了各种历代回顾,写了万字长文。为此购买的豪华版游戏和主机简直让我大出血!但PS4绝对值回票价,因为后来玩了上百小时的Bloodborne,最近还白金了。人生第一白,献给这么重口的游戏,我觉得我的性格已经被改变了。

天涯明月刀有很多老同事参与,我也玩了玩,画面不错,其他不想多说。PC上的怪猎OL移植版终于公测,风评不好,不敢试,遂作罢。

去年没怎么多玩Indie。Her Story是个非常妙的作品,深得我心,5小时通关。BattleBlock Theater也不错,玩着挺逗的,然而并不能让我不停的玩下去。Transistor让人眼前一亮,可惜去年AAA攻势凶猛,都统统搁置了。PS4会员给了好多Indie,但只有个潜行的动作游戏我稍微玩了玩,关卡太难弃了。

今年会继续推Dark Souls,并不准备完美通关,太累人了。这种hardcore游戏,体验体验就好,不能耽搁填坑大业。

是的,今年一定要填坑,说什么也不能拖了。