分类
项目与产品 开发经验

版本延误

上周四是要出0329中间版本的时候,在这一天发生了版本延误的问题,导致加班到晚上十二点多才结束。

发生这个问题的表面原因是,原本计划中这一天所出的版本是不包含引擎升级的内容的,而在晚上四五点的时候又决定要在这个版本中加入,而升级引擎的时候又导致某些尚未完成的功能合并代码的时候发生了问题,因此解决引擎升级,以及一些功能合并代码耽误了很久的时间。

有一些原因是客观的。由于这是年后第一次按照新的迭代计划来安排工作,因此在出中间版本和最终版本方面的计划上是第一次经历,在进度安排上经验不太足。第二个问题是这个版本正好还赶上了引擎升级,本身就是一个特殊的版本。第三个问题是当天办公楼的电信宽带还出了问题,导致出包上传速度极其缓慢。第四个问题是这个版本是跨年的版本,中间赶上了长时间的假期,节前有三天时间开发这个版本,因此节后只剩下了一周半,再加上过节请假导致人员不齐,所以这个版本不是以全力进行开发的。

但排除这些因素,还暴露了一个团队上进度安排的问题。在年前的时候就已经完成了引擎升级的工作,但我们在年后回来的进度会上还是一开始决定了这个中间版本不把引擎升级的代码合并进去,且团队成员一直在用老版本引擎的编辑器进行开发,这个安排是不合理的,这种内容赶早不赶晚,应该尽早让团队成员把编辑器的版本都升上去,而不是等到功能都开发完成后再升级引擎。当然,过早的升级编辑器也有风险,很可能导致新功能的开发受到阻碍,因此如何评估这个风险就暴露了另外一个问题:

安排进度的人,对于这个功能的风险评估是不充分的。到底应该尽早升级引擎还是等功能都做完了再升级引擎,事先并没有进行充分的讨论,因此基本可以说是迷迷糊糊的就确定了这个版本不升级引擎,而不升级的理由其实没有仔细想过。

因此以后这些程序独立作业的功能上,还是要加强沟通,完全的评估后作业内容和风险以及和其他功能互相影响的程度,再进行合理的安排。

分类
技术

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

好久没写博客了,今天趁着还在排魔兽副本的功夫上来写一篇!

由于之前没有经验,这个项目在做的时候,在多语言文本管理这方面做得很差,到了后期字符串基本成了一个无法管理的状态,随便要改点什么字都需要在一个存了所有游戏文本的5000多行的巨大txt中搜索,极其不便;而且有相当多的字符串是已经在游戏中删除掉的废字符串,但却依然停留在文本文档中。所以我想要总结一下经验,参考一些其他游戏的做法,看看能否用更好的方式来解决这个问题。

首先第一个要解决的问题是,如何让程序自动对应不同版本的语言?在设计界面的时候一定要方方面面都把这个考虑进去,否则一定会出问题,比如显示中文刚刚好,显示英文却太长了。不过这不是本文的重点,更多的相关内容可以看这篇文章。我们需要用ID来管理所有文本,比如说我们有个英雄,英雄的ID是100,他的说明文字就可能是hero_100_description之类的。ID的这种命名方式对于程序来说没有意义,不管是hero_100_description还是GameStringS1293IU634EASD,对于程序都可以正常运行,但采用后者会让字符串的可读性相当差,因此最好由策划来手动为所有需要用到的文本ID进行命名——就像美术人员会为所有美术资产命名一样。这种命名的好处还能让你轻易地剔除掉已经不再使用的废字符串。

ID可以按照统一的模块来起名(横向的),也可以按照实际的程序结构来起名(纵向的),个人建议采用后者的方式。假如按照前者的话,我们有可能将所有的UI使用到的文字都写作一样的内容,比如都叫UI_Title_XXX,但实际上游戏并不需要同时加载所有UI的文本,每个界面要用到的都很有限,因此按照程序结构来划分会更科学一些,这需要与游戏程序一同进行设计。不过由于纯文本文件往往都很小,不像美术资产一样会占用大量内存,因此在确保没问题的情况下偷懒一下,在任何地方都加载所有文本也可能可以,这还是需要看程序方面的意见。

ID的名字在允许的情况下,为了可读性,可以起的尽量的长,这需要与程序一同设计。比如,UI_MainMenu_NewGameButton_Normal,就说明了这个文字是用于显示UI的,是在主菜单用到的,是“新游戏”按钮在默认情况下的文字,这种清晰易懂的名字无论是程序在代码中还是策划在文本管理中都会让工作轻松得多。

如果需要制作新内容的时候,策划可以先添加所有需要的文本及其ID,再让程序制作,流程上也会更顺畅一些。如果某个字符串没有填写,则直接在游戏中显示其ID,这样能在游戏中轻易地发现是哪个字符串忘写了。

当某些东西的结构固定时,甚至可以统一、批量地先由程序生成ID,再有策划进行填写——比如英雄有100个,每个英雄都有描述,程序就可以先把hero_001_description到hero_100_description直接做到游戏中——《星际争霸2》就是这么干的。

如果字符串需要换行,建议使用在单个string中加入诸如n的方法,而不是使用多个string,因为同一句话不同语言显示出来行数往往不一样,如果用多个string的话ID管理会变得相当混乱,很可能中文一共有5000个ID而英文却有5010个ID,具体多了哪10个就是个要命的事情。文本的样式管理应该和程序、美术一同进行设计,尽量把文本的样式也写进string中再由程序解析,比如:

  • <string><c value = “FF0000”>我是一个红色的文本</c></string>
  • <string><b><c value = “FF0000”>我是一个红色加粗的文本</c></b></string>
  • <string><size = 24><b><c value = “FF0000”>我是一个红色加粗的24磅的文本</c></b></size></string>

这样做法的好处是在保留一定可读性的前提下,修改文本样式不再需要程序的协助,能够大大降低开发过程中的沟通成本。实际上这也是《星际争霸2》的做法。

不过笔者认为,《星际争霸2》也有不值得学习的地方,就是其不同语言文本的文件结构。由于该游戏支持相当多的语言,因此他们的做法是把不同的语言文本完全分离在不同的文件中,比如中文文本都存在zhCN中,英文文本都存在enUS中等等,这样的问题就是在两个文件中,我们都要以“ID+String”的方式进行管理,无法确保ID的唯一性。因此相比之下我更倾向于《魔兽世界》插件或者《炉石传说》的结构,将不同语言的文本全都放在同一个文件中,这对于策划以及游戏翻译外包来说是都是相当舒服的事情,下面是例子:

《魔兽世界》插件的多语言(以Decursive为例子):

## Title: Decursive |cffff00ff -Ace3-|r
## Notes: Afflictions display and cleaning for solo, group and raid with advanced filtering and priority system.
## Notes-frFR: Affichage et guérison des affections avec un système évolué de filtrage et de priorité.
## Notes-deDE: Anzeige und Reinigung von Gebrechen für Solo, Gruppe und Schlachtzug mit erweitertem Filter- und Prioritäten-System.
## Notes-esES: Afflictions display and cleaning for solo, group and raid with advanced filtering and priority system.
## Notes-esMX: Afflictions display and cleaning for solo, group and raid with advanced filtering and priority system.
## Notes-koKR: 쏠로, 파티, 공격대를 위한 고급화된 필터링과 시스템 우선권으로 고통들의 표시와 제거를 합니다.
## Notes-ruRU: Отображение и инструменты для развеивания дебаффов для одиночной игры, игры в группе и рейде, с развитой системой фильтрации и приоритетов.
## Notes-zhCN: 当单独、小队和团队时清除有害状态,并可使用高级过滤和优先等级系统。
## Notes-zhTW: 當單獨、小隊和團隊時清除有害狀態,並可使用高級過濾和優先等級系統。
## Notes-ptBR: Afflictions display and cleaning for solo, group and raid with advanced filtering and priority system.
## Notes-itIT: Afflictions display and cleaning for solo, group and raid with advanced filtering and priority system.

炉石传说的例子:

<Tag name=”FlavorText” enumID=”351″ type=”String”>
<enUS>Hogger is super powerful. If you kill him, it’s because he &lt;i&gt;let&lt;/i&gt; you.</enUS>
<zhTW>霍格非常強。如果你殺死他,那是因為他&lt;i&gt;讓&lt;/i&gt;你殺他。</zhTW>
<zhCN>霍格可是超级厉害的。如果你杀了他,只是因为他让你这么做的。</zhCN>
<ruRU>Дробитель ужасно сильный. Если вы убьете его, то это значит, что он вам &lt;i&gt;поддался&lt;/i&gt;.</ruRU>
<ptBR>Hogger é superpoderoso. Se conseguir matá-lo, foi porque ele &lt;i&gt;deixou&lt;/i&gt;.</ptBR>
<plPL>Wyżer jest supermocny. Jeśli go zabijesz, to tylko dlatego, że ci na to &lt;i&gt;pozwolił&lt;/i&gt;.</plPL>
<koKR>들창코는 정말 강력합니다. 만약 처치했다면, 그가 &lt;i&gt;봐줬기&lt;/i&gt; 때문입니다.</koKR>
<itIT>Boccalarga è potentissimo. Se lo uccidi è solo perché lui te lo ha permesso.</itIT>
<frFR>Lardeur est super fort. Si vous réussissez à le tuer, c’est uniquement parce qu’il vous aura &lt;i&gt;laissé&lt;/i&gt; faire.</frFR>
<esMX>Hogger es muy poderoso. Si lo matas, es porque &lt;i&gt;él&lt;/i&gt; así lo quiso.</esMX>
<esES>Hogger ya se ha cobrado más víctimas que el Cataclismo.</esES>
<deDE>Hogger ist so mächtig, dass Ihr ihn nur töten könnt, wenn er Euch &lt;i&gt;lässt&lt;/i&gt;.</deDE>
</Tag>

不过这种做法也有一个难题,就是如果新加一个语种的话会影响到之前的所有结构,所以无论采取哪种结构,最好都有文本管理工具,而不是直接手写txt。但比起传统而常见的每个语言一个文件其中把所有系统需要的文本都丢进去,我更倾向于按照系统划分文本文件,然后把所有语言的丢进同一个文本中。当然了,这还是要看程序是如何设计的,以及游戏的过程中是否支持切换语言。

如果你有更好的做法,欢迎和我交流经验,我的博客地址是www.maniahero.com!

分类
琐事 技术

redbooth:让一切变得井井有条

最近我在使用redbooth来管理工作进度,这是一个非常好用的项目管理软件,基于网页,只有英文版,其官方网站是https://redbooth.com。

由于我经常会迷迷糊糊地记不得自己该干嘛,因此这个网站的帮助很大。

redbooth是以组织和项目驱动的。组织就像是一伙一起玩游戏的玩家组成的一个队伍,项目就是这群玩家们要去攻克的副本。用户可以在项目中创建任务并发布给每个成员,成员们可以在项目中添加文本记录或上传文件,还可以在项目中进行对话,对于小型团队来说该有的功能已经都有了,最重要的是其简单易懂,不像很多国产的高大上项目管理软件一样满页都是让人看不懂的装有名词,特别亲民,只要三五分钟就能学会怎么用。

用户可以直接分享项目内的文本,邀请其他用户加入,可是免费版一个项目最多只能有5个成员,但这对于小型团队来说也足够用了。

每天redbooth还能根据你的设定向你的邮箱中发送尚未完成的任务列表,每个任务还能创建子任务——这样就能把一个大任务拆分成多个小任务,用户还可以按照多种方法排序、检索任务,还能够查阅甘特图。当一个任务乃至一个工程完成后,玩家还可以将其打包封档,以供日后查阅。

虽然只有英文版,但由于界面清晰友好,上手难度还算不高,而且国内访问速度也很快,redbooth还可以绑定dropbox、google的账户,这更使其如虎添翼。

对于任何团队,尤其是经验不足的新手团队来说,项目管理都是重中之重的,有了redbooth的帮助更容易把成员凝聚起来,一起推动项目木向前走。