分类
游戏设计

游戏设计就是游戏设计史

大家好我是AT君,在哲学领域有一句话叫“哲学就是哲学史”,我发现这句话同样适用于游戏设计领域,因此有了本文的标题。

回答游戏设计是什么,就必须回答游戏是什么,以及设计是什么,目前我心目中的答案是这两个:

  • 游戏是由规则创造的体验(A game is an experience created by rules);
  • 设计是解决问题(Design is problem solving)。

二者结合下来,游戏设计就是通过不断解决设计问题来实现设计师想要的游戏体验的创作过程

设计师所面临的问题,以及想要创作的体验,往往都是建立在前人的基础之上的,因此研究、学习游戏设计的过程,实际上就是研究不同作品之间的创作脉络,或者说作品的序列。每一款作品都是基于某个前作所构建而来的,他们尝试解决了前作的某些问题,优化了前作的某些方面,对前作进行改造使其更加适应新的时代,并且同时也可能产生一些新的问题,留给后续的作品去解决。

一条创作脉络清晰的作品序列往往都是同一个类型的游戏,但不一定都是一个IP的游戏。我们经常能听到某某游戏精神续作的说法,这意味着在游戏设计角度它是延续自某个作品的,而在商业品牌角度很可能是另起了一个和之前的作品毫无关系的IP。

抛开商业层面是否成功不谈,纯粹的从游戏设计角度来看,一个作品序列中往往存在着这样几种地位的作品:

  • T0:开山立派的作品,从游戏设计上来说是祖师爷级别的作品,这些作品往往定义了一个全新的游戏品类,或至少可以将类似的作品称作“某某like”。
  • T1:使整个作品序列产生一定突破的作品,让整个作品序列得到一定程度的发展,甚至引领了一个全新的时代的伟大作品。
  • T2:一般的作品,从游戏设计上来说没有给整个序列带来特别大的新突破,或者进行了一些尝试但没有被认可,整体来说最终的效果中规中矩。
  • T3:失败作,不但没有解决序列中前作的问题,同时产生了大量的设计问题。再次强调,这是从纯粹的游戏设计角度而非商业角度。

我们作为游戏设计师的追求至少是第三个档次的作品,而能够做到第一个档次的设计师可以认为是世界级的大师了。

我们既可以从整个游戏作品序列的宏观角度(比如MOBA的发展史、FPS的发展史、MMO的发展史、开放世界的发展史)来查看游戏发展的脉络,也可以从某个游戏系统设计的微观角度来查看游戏发展的脉络。前者要写起来太过复杂,我认为大部分游戏设计师能够完全吃透一两个作品序列就已经足够安身立命了,所以本文准备从后者找一个例子来说明。

比如FPS中的换子弹系统,在最早的FPS中是没有换弹机制的,玩家之间见面互射看谁能打死对方靠的是纯粹的精准以及移动能力。加入了换弹后的FPS游戏玩家要在交战中考虑换弹时机,大大增加了游戏的战术性。到后来《无主之地》和《战争机器》等游戏进一步在换子弹这个机制上做了一些尝试,不过都没成为新的主流设计。到了军事对战游戏中,由于换弹速度极慢,因此又产生了衍生的追求精度、规划走位、养成换弹速度等玩法。到如今完全没有换弹机制的射击游戏已经几乎不存在了,这成为了FPS游戏中的一个基本设计——就算某些武器真的没有弹夹,往往也会有类似的过热或者过载机制来限制玩家无脑开火。

FPS中还有一个值得讨论的设计就是“呼吸回血大法”。最早的FPS中玩家都是100格血,需要跑来跑去满地捡血包吃,甚至可以吃护甲片让血量突破100,甚至枪也靠玩家去捡。这个设计导致的问题是在大乱斗对战玩法中会出现占据统治性优势,因为复活点是固定的,武器刷新点也是固定的,对方不可能再给你拿到优势武器的机会,FPS游戏玩到后面变成了控图游戏,而控图并不利于FPS的本质体验——在对方射死自己之前射死对方,因此后面的游戏基本都放弃了满地捡枪的设计。

《光晕》最早加入了能量护盾的设计,脱战一段时间后就可以快速回满,这一设计可以说和弹夹的设计是相辅相成的——你不会当着别人的面换弹夹,那么躲起来换弹夹的时候自然也获得了喘息的机会。一个没有子弹没有血量的对手一旦脱离战斗足够久也能反杀你一个回马枪,因此游戏的战术性进一步得到了提升,你再也不需要和人火拼一番后像吃豆人一样沿着地图管道狂奔,只为了尽快把血回到100了。

这个呼吸回血大法后来逐渐成了FPS游戏的标配,FPS游戏甚至逐渐都移除了血条的设计,然而这导致了一个问题——《光晕》是科幻游戏,护盾可以充能是说得通的,而一个现代的游戏就不行了,一个被炸个半死、扫了几梭子子弹的大兵或者警探,爬进壕沟或者躲在路障20秒后就又生龙活虎了?这怎么也说不通,所以被人戏称为“呼吸回血大法”。类似的衍生问题还有诸如“洗手战神”、“掰手指回血”等等。

我相信这两个例子足以说明游戏设计到底在做些什么,以及为什么游戏设计就是游戏设计史了。那么,这到底有什么意义呢?

我觉得,最大的意义在于这能让我们分清楚自己到底是在抄袭还是在创新,以及创新的时候真的是在解决问题,还是只是在拍脑袋想当然。如果你负责的某个功能,你不了解别的游戏是经过了怎样的发展脉络为什么设计成这个样子的,以及存在什么问题,那你就只能无脑抄袭,虽然没法解决这个问题,但至少也不会犯什么新的错误,而在这种情况下,你负责的这个模块自然而然就划入了T2的水平,变得平庸。不过这至少比拍脑袋想当然好,因为那更大概率会让你负责的这个模块变成T3的失败作。

当然,大部分人的大部分职业生涯都是在做T2这个水平的作品,但我相信所有人都有着更进一步的愿望的,那怎么能从T2向T1迈出第一步,就是要从了解游戏设计史开始了。

正所谓温故而知新,可以为师矣,对于游戏设计来说也是如此。

分类
未分类

游戏开发中的多语言文本管理2

前一阵子在做新项目的时候想了一下目前的项目在本地化文本管理方面遇到的诸多问题,正好又碰到了一个新朋友来问这个问题,翻出了7年前我写的一篇博客,现在回头看的话感觉当时写的太简陋了,因此决定重新分享我的个人经验,在多语言文本管理中遇到的问题,以及我建议的解决方法。

中心化管理:看起来很美

市面上最常见的多语言文本管理的手段是中心化的管理手段,即多语言文本完全脱离其所被使用的场合,作为一个单独的表单或文件存在,任何需要显示文本的地方,都以key为唯一的索引从这个文本中来获取对应的本地化语言的文本。

在举一个具体的例子之前,我们要明确一个观点:一个项目中的文本主要分两种:UI文本和数据文本。UI文本指的是界面上各种控件显示的文本,数据文本则是需要策划管理的游戏数据的文本。除此之外还有第三种文本:服务器文本,这个属于比较特殊的情况,不在下面的例子中讨论,文章结尾的地方会专门说明。

假如我们在做一款RPG游戏,有英雄和技能两个表,最终导出了三个文件,那么一个典型的中心化管理的多语言文本可能是这样设计的文件结构:

  • hero.json
  • skill.json
  • text.json

我们只看hero.json和text.json来说明问题。

假设一个英雄非常简单,只有两个属性:名字、技能,那么英雄的数据可能长这样:

  • hero_id = 1
  • hero_name = “text_hero_name_001”
  • hero_skill = [1,2,3]

本文重点关注的即是hero_name的部分,这是需要多语言管理的部分。显然“text_hero_name_001”是一个key,其指向的真实文本储存于text.json中。

那么text.json长什么样?如果我们用同一个text.json来存储全部多语言的文本,那么可能长得类似这样(Dictionary/Object风格):

  • text_hero_name_001 =
    • {
      • “zh_CN” : “王老王”,
      • “en_US” : “King Old King”,
    • }

也可能是这样(CSV风格):

  • key,”zh_CN”,”en_US”,
  • text_hero_name_001,”王老王”,”King Old King”,

也可能是每个语言对应一个text.json文件,这种就不再举例赘述,但不管哪种,本质都是一样的:文本脱离于其所被使用的环境,进行中心化管理,并且在被使用的地方通过Key来索引。

这看起来没有任何问题,也是业界的主流做法,但在我这些年游戏开发的经验中却觉得这样做的问题非常大,甚至可以说这都是程序思维的产物,能实现需求但却基本没考虑策划和UI的维护成本,下面就开始详细的阐述这种方式的弊端。

问题一:脱离使用环境

假设你是一个UI同学,现在做了一个简单的弹出层,有标题、正文和确定按钮,你需要三个文本来描述这个界面:

  • 标题:确认充值?
  • 正文:做游戏不赚钱,就是交个朋友。确认充值648钻?
  • 按钮:确认

那么按照上述的管理方式,界面上可能是这样的:

  • 标题:text_dialogue_title_iap_001
  • 正文:text_dialogue_content_iap_001
  • 按钮:text_dialogue_button_iap_001

一个UI同学在UI编辑器或游戏引擎中长久的面对这种不可读、不可排版的文本,长此以往对心灵会产生什么样的打击不言而喻——当然,这跟程序没关系,程序也不在乎。

假如UI抱怨的非常凶,要求程序在编辑环境中也要默认把这堆看不懂的key给显示成简体中文,而程序勉为其难的也给做了,那么至少解决了UI同学的问题,但前文提过,UI文本只是一个项目中的一部分,还有另外一个大头:数据文本

还是刚才的hero.json的例子,假如我们这个RPG项目有100个英雄,那么我们在hero.json中能看到的是什么呢?是任何一个英雄你都不知道他的名字是什么,只能看到从text_hero_name_001到text_hero_name_100这种意义不明的东西。

作为一个策划,你不太可能记得住一个英雄的ID,反而记住他的名字要容易得多。那么现在你要去找一个英雄的数据,你要怎么办?你可能要去text.json中找到这个英雄的名字,再看对应的key来识别他的ID,再去hero.json中找到这个英雄的数据。

这时候假如有个策划不那么讲究,没按照规范去好好的给hero_name对应的文本建key,并且当时他偷摸就提交了,谁也不知道,本来应该叫做”text_hero_name_100″,但这个策划给起成了”text_hero_name_wanglaowang”,那你找起来就会想杀人了。

这时候还有更大的问题,如果一个策划想要知道一个英雄有什么技能,那怎么办?因为技能表里也是不带名字的,他就只能先想办法找到英雄的ID,然后再找到技能的ID,然后再去看技能的名字

这种套娃操作每多一层,策划的心理都会多一层崩溃。

除此之外,脱离使用环境还使得你的项目需要翻译外包的时候看似容易,只要把text.json丢过去就行了,但因为翻译的人员不知道这个文本是用在哪里的,因此很容易出现翻译完了结合上下文意义错误或UI的显示出现异常的情况。这部分的沟通成本也是相当巨大的。

问题二:单一职能原则

假设我们还是上面那个做充值对话框的UI同学。这个项目肯定不止这样一个对话框,所以我们还会做很多很多其他的对话框,比如购买各种东西的确认对话框、各种危险操作的确认对话框、需要选择个数或者填写内容再提交的对话框等等。

做多了之后我们就会发现,这些对话框都有一个确定按钮,而且按钮的文本内容可能都一样,都是“确定”,但却每次都要起一个新的text的key。当这个UI同学打开了text.json后,发现有几十上百个不同key的文本都叫“确定”的时候,他一定会怀疑这种做法是不是有问题。

最后UI们商量了一下,决定所有的确定按钮都用一个key,比如这个key叫做“text_dialogue_button_confirm”。大家觉得工作简单多了,所有的确定按钮都用这一个文本,不用再弄大量臃肿的文本了。

直到再过了一段时间,策划提了一个需求,充值界面的确认按钮不能只写“确认”,要写“确认,我家有矿”。策划认为简单的改文本就行,于是就把“text_dialogue_button_confirm”的内容给直接改了。

改完了之后发现项目出了大问题,所有的对话框的确认按钮的文本都变成了“确认,我家有矿”。然后QA爸爸就提着刀过来了。

QA爸爸把这个问题捅到了项目主管那里,等到项目主管发现这个问题之后,决定检查一下所有的text.json里面的文本,要确认下到底有哪条key是不止被用了一次的,但却发现很难做到这样,因为项目进展到这个阶段,text.json里面可能已经有上万条数据了,你既没法简单的知道里面有没有完全没被引用实际上已经冗余了的条目(比如删了一个技能,但技能的名字没删),也没法确认里面的某一个条目有没有被多次引用(类似上面的确认的问题,策划和美术都会有这个情况),从而导致改动的时候引发意料之外的问题。

当然,你可以硬性的规定,凡是要复用的text都放到同一个文件里(比如它叫general_text.json),凡是应该被用且应该只被引用一次的text都放在text.json里,但毕竟只要key是人为的手写的,就无法完全避免这个问题,很快两个文件里面可能又会出现混乱——text.json里面出现了被引用多次的key,而general_text.json里面出现了冗余的key。

假设这时候有一个程序同学觉得可以从工具上来入手解决这个问题,于是他写了一个工具,从此text.json的key都是自动管理的了,策划同学可以方便的在各个数据表中添加、修改、删除文本,key的关联都是自动完成的,或者说text.json的key完全都由这个工具自动管理了,key甚至对策划来说是不可见的,从而从根本上避免了策划手误的问题。

这听起来很美好是吧?但其实并不是的,因为这个方案依然有问题。

从原则上来说我个人是非常不建议项目在常规的开发工作流中加入一些自己开发的工具的,除非是在这方面有相当丰富经验的开发团队,或者这个工具本身足够简单、不进入工作流(比如用了一次就不用了的“日抛型”工具)。原因有三点。

首先是这个工具的可维护性问题。这些工具在开发之时只是为了尽快的解决某些小问题,并没有严格的当做一款可以交付使用的产品来对待,因此缺乏文档,并且开发的也相对随意(用户是内部开发人员而不是游戏玩家)。这个工具本身需要测试但缺乏测试,它的完整性和可靠性需要支付相当大的成本,而这部分成本本来是可以去开发玩家可以体验到的功能的。这还只是短期的问题,如果我们从长计议的话,短期少做点功能,把工具做好,也没什么问题,但长期问题实际上更大。当这个工具被用了几个月甚至几年之后,不出bug的概率几乎等于0,而当初写这个工具的人可能早已不在这个项目组甚至离职了,而由于缺乏文档且开发随意,接手维护这个工具的人可能完全无法上手,这种情况下项目就陷入了一个两难的境地。还有很多情况下,随着工作流的调整或人员的变化,慢慢的这个工具也会被不断的迭代,但其迭代的速度往往是滞后于团队的变化的,甚至最终成为拖后腿的卡点——你不得不用它,而你又明知道它已经不好用了。

其次是这个工具的可靠性问题。这些工具所依赖的开发环境过于复杂,公司的一次停电、游戏引擎的一次升级、一个脏数据的写入、一个策划不小心的误操作(比如把ID填重复了),都有可能产生大量的问题,这些问题是最早做工具的同学所意料不到的(大家都知道,程序员是乐观的),而为了解决这些问题所有的策划都不得不停工,并且问题解决的代价和效果也不得而知(比如可能导致json中的所有排序都变了,虽然实际上没变化因为json里面排序不重要,但QA爸爸能看到的就是一个上万行的json文件的每一行都变了,而导致QA爸爸提着刀过来)。

最后一旦你开始依赖这种小工具后,往往会接二连三的做一大堆工具,前面的两个问题很快会变成多个问题,很快就会陷入按下葫芦起了瓢的状态,甚至当出了问题之后你都不知道究竟是哪个小工具的锅,开发工具的人抱怨使用工具的人提的问题模糊而不确定(甚至怀疑是使用者自己的问题),使用工具的人抱怨开发工具的人做的破玩意不靠谱,最终所有人都难受。

因此,如果你必须要把某个工具加入工作流中,那么如果有外部的、成熟的、有长期维护的解决方案,尽量不要自己造轮子,宁可花点钱买解决方案,也比自己花精力去做这些事情要强,否则当你过了几个月甚至几年后,一定会为当初自己的决定后悔——假如你还在这个项目组的话。

要相信你的问题别人都早就遇到过了,用别人造好的轮子总是比自己造轮子强,人类社会就是这么进步的。

问题三:依赖性问题

假如你是一个策划,已经设计好了一个新的英雄,以及他的技能,现在要开始配表了。

既然要加英雄,那么理所当然的你打开了hero.json,但是当你加到一半的时候发现加不下去了,因为hero_name需要一个key,你必须先去text.json里面配置好这个文本,再填回到hero.json中来才能完成配置。提交的时候你必须同时提交这两个文件,否则英雄的名字就会显示错误,显然这是会被QA爸爸暴揍的。

等你搞完了之后又发现这个英雄要加技能,那必须又先去配技能表。而配技能表的时候又发现了必须要去先去text.json里面写好技能的名字。

而现实情况中这个套娃的情况往往更严重,以我目前的项目为例,我需要新加一个宝箱,这个宝箱有【名字】有【描述】,这个宝箱有一个对应的道具ID,道具有【名字】有【描述】,这个宝箱里面是一件新时装,这个时装有【名字】有【描述】,这个新时装有对应的道具ID, 道具有【名字】有【描述】,这个新时装有对应的时装碎片,这个碎片有【名字】有【描述】,这个碎片有对应的道具 ID , 道具有【名字】有【描述】。等这一套折腾完,你会发现最耗费精力的不是宝箱->时装->碎片的套娃,而是不管你干啥都需要去text.json里面加名字,而这对于策划来说也是非常痛苦的。

当然,在删除配置的时候策划也会面对同样的噩梦,要删一个东西就要删大量对应的text,而这种删除操作的危险性在上面的一个问题中已经提到过了,因此最终往往会演变成“冗余就冗余,只加不减就好了, 这样至少不会出错”的情况。这会导致外包成本急剧增加,因为你也不知道哪些文本有用,哪些文本没用的。

更严重的是这会让你的项目很屎,而这屎不是喂给玩家的,是喂给策划的。大家都知道这里面充满了屎,但谁也没法认出来究竟哪些是屎。一个敢喂自己屎的策划,对玩家能做出多么丧心病狂的决策都是有可能的。

当一个东西变得反直觉的时候,大概率有更好的方案可以去替代它。

问题四:冲突问题

极端的情况下,不管你改客户端的什么表,都需要同时的去改text.json。而text.json只有一个,所有策划共用,因此冲突的几率极高,同时类似SVN的版本管理工具对json文件的比对支持的也不是特别好(你可能需要专门的json语意比对工具),于是策划的作业变成了一场噩梦,你只是想把自己改的东西提交上去而已,但却发现这竟然如此困难。

而更大的问题是,你不只是提交就完事了,你还需要合并呢,合并的时候更是一场噩梦。

虽然靠培训每个人都要学会提交、合并、解决冲突可以来克服这个困难,但毕竟这个困难实际上……有可能压根就不存在,而只是因为一开始设计的偷懒导致的没必要的困难。你让程序把所有代码都写在一个文件里他们自然不干,那为什么策划和UI的所有文本都在一个文件里他们就干了呢?——因为不用他们维护,这是个屁股决定脑袋的问题。

问题五:唯一性问题

由于大量的文本都堆在一个文件里,为了保持key的可读性和唯一性,命名就成了一大难题,其困难程度甚至比美术同学考虑美术资源的命名还困难,因为美术资源可以分文件夹,但key都堆在一起。

想找到一套完美的可以描述所有东西的key的方法不是不行,但这种结果大概率会让key变得非常冗长。比如美术可能考虑把界面的名字或者prefab的名字加进去,策划则要把是哪个表的哪个id的哪个字段用到的加进去。很快你的项目就会出现一个神奇的现象:大部分的字符串的key甚至比其本身的内容还要长的多的多,整个text.json文件奇大无比,但“三斤鸭子两斤嘴”,肉没多少。这种情况的体验就像是大家上班的时候互相不叫昵称也不叫姓名,而是互相喊身份证号的完整号码来互相沟通一样,显得非常蠢。

那怎么办?

解决方法我觉得很简单,去中心化,直接对症下药,需要完成以下几个需求:

  • 文本不再中心化全放在一起,而是分散开来,根据各个模块分散到各个文件中,并且把程序设计成只能访问自己相关模块的文本。这样即能解决一个大文件策划互相冲突的问题,也能解决滥用key的引用导致无法追踪每个key都被哪里用到了问题。一言以蔽之,把text从全局的改成本地的。
  • 文本尽量贴近其所被使用的场合,甚至可以完全免掉key是最好的。这样既不用费劲去给key取名字,也不用去琢磨key的冗余或被多次引用的问题了,也不用去开发劳什子自动关联key的工具了。

于是hero.json会变成什么样子?大概会变成这样:

  • hero_id = 1
  • hero_name =
    • {
      • “zh_CN” : “王老王”
      • “en_US” : “King Old King”
    • }
  • hero_skill = [1,2,3]

回头一看,这其实就是我七年前贴的文章中《炉石传说》的做法。暴雪在《星际争霸2》中采用的还是中心化的管理办法,而《炉石传说》他们选择了另外的做法,我猜是他们吃屎吃够了。

如果策划用Excel来管理多语言的话,需要写插件,否则一个格子里面写Dictonary/Object风格的东西会很蛋疼;或者策划可以在多列中配置语言,但最终把多列导出成Dictionary/Object风格的内容。但是毕竟长痛不如短痛,总比搞好几个表来回贴key要舒服得多。

有人可能说了,这样策划要每次都去写”zh_CN”和”en_US”这种文本,不很容易错吗?但你想想,是写这样固定的文本容易错,还是每次都要依照一个规则去想一个新的key更容易错呢?

还有人可能会说,这样客户端不管当前语言是什么,都会加载全部的语言文本,有点浪费资源。但根据我个人的理解,占内存大头的永远不会是文本文本,而是二进制文件,因此这方面的性能问题也可以忽略不计。反而这可能成为一个好处,即切换语言不需要重启客户端更容易实现了,但毕竟我不是专业的程序,这里可能还涉及到加载字体等问题,这里要视项目最初的需求是否需要不重启客户端就能切换语言了。

好了,策划的同学解决完了,那么UI同学怎么办?

比较简单的做法是扩展一个支持多语言的控件,比如原本系统的文本控件只能输入一套文本,让程序扩展一下可以写多套文本即可,同时默认显示中文。比如一个确定按钮,本来UI拉上来一个button后直接在text里面写“确定”就行了,现在的话会有多行的text,其中第一行是”zh_CN”的,UI同学要在这里写”确定”,然后在第二行”en_US”里面写”Confirm”。同时还可以支持切换预览多语言效果。实际上很多多语言插件都是用类似的思路去做的,比如Unity的I2 Language(这里不是打广告,我没用过,但看demo感觉挺好用的,还支持图片和音频的多语言,而且这也是Unity Asset Store中最受欢迎的本地化插件)。

UI文本本地化之后的一个问题就是外包的时候我们还是需要导出文本,因此在一开始设计结构的时候需要尽量设计一个不依赖于Key同时还可以方便导出导入的结构,单独把每个界面prefab的文本导出,翻译完成后再导回来即可。上面提过的I2 Language貌似还支持谷歌翻译以及导入导出功能(这插件本质上还是中心化管理文本的,只是界面上隐藏了),感兴趣的同学可以自己试试。

但是以上毕竟只是脑洞,我决定在新项目中试一下用这种方式来管理文本的实际效果如何。因为都是我一个人做的,所以UI的多语言文本我决定不写在控件上,而写在代码里,一个prefab的代码把需要用到的文本统一在一个地方以Dictonary/Object的风格来声明好,方便后面调用。而策划配表的部分,我决定在Excel中每个文本一列,再导出的时候把同一个key的文本合并成Dictonary/Object风格的变量。

这里实际也引申出了另外两个关于UI实现问题。

第一个问题是Prefab这个东西往往是客户端程序和UI同学都要打交道的,这里非常容易出现问题,比如UI同学一不小心把某个节点隐藏了,QA同学提了BUG,程序同学绞尽脑汁的去调查问题最终发现居然不是自己的锅。解决方案业内也有一些,有的比较笨的办法是由程序同学来拼界面,这样避免UI同学染指Prefab,但拼完了难免坐标不对,UI同学要再调整一下;有的方法则是参考策划的工作流,把UI的编辑过程独立于游戏引擎之外,把界面当做是资源文件导入到项目中,从而实现了UI同学和程序同学作业对象的分离。也有其他的做法,比如对UI设计师和UI程序员的要求更高,双方必须紧密的结对作业,而不是各自分属不同的部门。还有的做法是UI在PhotoShop里面做完了工作后策划来拼界面,把和程序对接的工作交给了策划,从而UI不用考虑上传SVN的问题。还有的做法是逼着UI同学去学写代码,比如至少会用个蓝图啥的,从而避免程序同学染指Prefab。反正各种奇奇怪怪的做法都有,哪种是最好的不好说,要视团队和项目的具体情况而定。以上的种种方法中我个人最倾向的是哪种?如果是UI表现十分重要的游戏,那么提高对UI和程序人才素质的要求,强制其结对作业共同对UI的结果负责,是比较好的解决手段,能够实现质量和性能都比较出色的UI界面,但这样对人才的要求很高(相当于半个TA),大部分的团队不一定能做到,这种情况下另外一个选择是退而求其次,将UI的设计工作交给策划,只保证功能性但不保证美观度,在人力捉襟见肘的小公司/独立团队或功能无限庞杂的大项目中这也是个不错的方法。不管哪种,其本质都是要适应UI工作的特殊性,这不是一个可以简单的“美术vs程序”二元割裂的工作,而是必须有机的结合在一起才能完成的综合性工作,一切想着切割UI和程序的工作流的方案都注定不是最优的。

第二个问题是界面的很多状态和内容应该是以资源驱动为主导还是以代码驱动为主导?比如一个界面默认状态是应该隐藏的,那么是UI同学把隐藏给勾上比较好,还是程序同学在代码里初始化的部分写上强制隐藏好?按照我的倾向性的话,如果不影响性能的前提下,我倾向于用代码来控制。UI资源本身毕竟是静态的,因此凡是动态的东西都应该由代码来控制,这也是为什么多语言文本我觉得写在代码中比挂在界面上要好的原因,因为涉及到多语言,本身就已经不是静态的文本了。

祝我好运吧emmmm,前途未卜,不知道还会踩到多少坑,但总比现在的情况舒服。

(另外别问我为什么我不用I2 Language,因为Godot天下第一)

写在最后:关于服务器文本

所谓的服务器文本,即并列于UI文本和数据文本之外的第三类文本,这种文本常见的是停服公告、发给玩家的邮件、紧急维护通知跑马灯等种种由于具体写什么文本完全无法预估而只能在服务器端设置文本,客户端收到什么就显示什么的文本。这类文本大部分属于运营工具的范畴。

那么这类文本如何实现本地化?

这首先要看游戏服务器的结构,是各个语言的用户都混在一个服务器里面玩?还是每个语言的用户自己有自己的服务器?如果是后者的话那么很简单,每个语言的服务器发对应语言的公告就好了(甚至可能是完全不同的运营商),如果是前者那么这涉及到另外一个问题:客户端能否切换多语言?如果能的话,比如我用英文客户端登录之后,系统发给我的邮件可能是英语写的,这时候我切换成中文客户端重登后,看到的这封邮件是英文的还是中文的呢?确定了这个需求之后,才能设计服务器端文本的多语言是应该如何处理的。

只要提前考虑好,程序做起来都是很容易的。难的都是已经在线上跑了一阵子了又不得不改,这才是最难受的。

分类
赏析与学习

哥斯拉的原罪

前一阵子看了王德峰的《中西方文化差异的渊源》,其中一个根本差别是东方人和西方人在理解“人和自然的关系”这块有着根本性的差距。

西方文化中普遍的态度是追求真理,改造自然,征服自然,人是主体,自然是客体,是主动改造者与被动的被改造者的关系,人与自然的关系是对立的关系。

东方文化中的普遍态度是敬畏上苍,讲究天人合一,人是世间万物中的沧海一粟,并没有什么特殊性,道法自然,万法皆空,人在自然中,自然也在人中,人与自然的关系是统一的。

这一方面解释了为什么工业革命出现在西方,一方面也解释了为什么哥斯拉出现在东方。

如果我们对人类改造自然、追求工业化、追求资本化的正义性抱有怀疑(这是大部分东方国家在走西方现代化路线中都会表现出来的反思,日本和韩国经济发展的更早,所以反思的更早),即“人类获得了本不应该获得的禁忌力量”,那么就会很自然的把对此的反噬具象化为哥斯拉,也因此定义了哥斯拉的一系列特征:

  • 哥斯拉是非善非恶的自然存在,或者说是超越善恶的存在。
  • 哥斯拉是无法被完全消灭的,因为人无法完全脱离自然,而有自然就会有自然灾害。
  • 哥斯拉是地球意志的化身,因此哥斯拉也看做成为地球的守护神,这种概念和神道教万物有灵的概念很像,山有山神,河有河神,地球自然也有地球神。
  • 《金刚大战哥斯拉》中,金刚对代表“无辜”的人类小女孩是友善的、平等的关系。
  • 《哥斯拉2:怪兽之王》中,基多拉摧毁地球的动机并没有被充分解释。唯一的解释是基多拉是外来的,因此是“邪恶”的。这个逻辑本质上是站不住脚的,因为单纯的排外虽然是人性的弱点,但是是不道德的。
  • 《金刚大战哥斯拉》中,最终扮演“恶役”的是人造的机械哥斯拉,并且再次由于人类妄想掌控自己所不应该掌控的禁忌力量,最终被基多拉上身。

从以上东西方的差距上也可以解释为什么《哥斯拉2:怪兽之王》中有那么多亚裔演员,章子怡和渡边谦扮演的角色都不赞同简单粗暴的干掉哥斯拉,而渡边谦甚至为了给哥斯拉加血加buff自爆了。而白人主角依然走的是好莱坞传统的“爱与家庭”的核心价值观,黑人配角们则单纯为了露脸而露脸,存在感弱于亚裔配角,因为这部影片既不需要他们来“爱与家庭”,也不需要他们来“天人合一”,因此黑人们主要都是扮演军人的戏份,代表了“人的力量”——当然,因为军人们也可以让白人演,因此不如说这是单纯的政治正确或对黑人的刻板印象。

显然,“人类所不应该获得的禁忌力量”这一概念本身,就对掌控自然、改造自然保持着悲观态度,同时还抱有道德批判,而这种思潮是东方的而非西方的。

当然,这里的“禁忌的力量”并不只是核能一种形态,也可能是其他方面的技术,比如基因改造、人造人(仿生人)、洗脑等等。这也是和赛博朋克的主要区别,赛博朋克探讨的主题往往是贫富差距、阶级对立等资本主义的原罪,而“禁忌的力量”往往是更广泛、更简单、也更根本的科幻题材。

大部分的文艺作品对于这种“禁忌的力量”的探讨,最终都会站在比较正能量的、保守的、人道主义的观点这一边,比如《西部世界》,哥斯拉自然也不能免俗。

比较不客气地说,这种阵营的选择本质上是讨好大众的,因为这观点并不是世界的真相,而是大众的期待。在系统性的罪恶面前,大部分大众并不会去反抗,而是会“打不过就加入”,这才是常态。比起消除社会差距,大众的想法而自己成为人上人,而不是消除差距,因此如果一部作品建立在完全消除了差异的基础上,那么必然是反主流道德的,最终这个形态的社会一定会被推翻,比如《V字仇杀队》和《撕裂的末日》。

也就是说,大众看着某一小撮反派“掌控了禁忌的力量而遭反噬”感觉很爽,但实际上这个前提是建立在“我自己是没法掌控这种禁忌的力量”之上的。这一小撮反派是脱离群众的,是可恶的资本家、恐怖分子、战争狂人、邪教徒或外星人。这也是为什么我对《神奇女侠1984》刚到惋惜的原因,这部电影的反派是前所罕见的“大众恶意”的集合体,是一个“乌合之众”的化身,而不是前面所说的千篇一律的脱离大众的反派,是一个比较深刻的主题,可惜最后拍了个稀烂。

而如果大众有可能掌控禁忌的力量,他会做出什么样的行为就不好说了,依我看,大部分人都是并不在乎遭到反噬也要去爽一把,成为人上人的。能够剖析到这一层的作品非常少,这也是为什么《蝙蝠侠:黑暗骑士》是一部佳作的重点原因之一。当我们看到壮汉黑人囚犯将引爆器扔出舷窗时,对人性光辉的歌颂是入木三分的。

归根结底,哥斯拉代表的其实是现代人类的原罪,而其之所以能够成为原罪,是因为大众对人与自然的预期的关系与实际的关系产生了偏差,所以哥斯拉成为了想象的神罚,来将事情修正为“其本来应该成为的样子”,虽然这是完全的意淫。

讨好大众的观点虽然畅销,但也注定浅薄,无法成为最优秀的艺术品。市场上不乏对人性剖析深刻的冷门佳作,但作为创作者的话,想必大家追求的都还是《蝙蝠侠:黑暗骑士》这种兼顾通俗与深刻的作品吧。