唯一游戏攻略网

暴雪工程师访谈趣闻:隐形兔子戏法屡试不爽

今年我有幸在现场经历了所有的工程师访谈,两场综合访谈,一场魔兽世界,都是QA性质。

因为都在三楼的副会场,所以在楼下主会场忙碌的媒体往往不会顾及这里,感觉不分享出来可能就没人分享了。

主要感受就是相比去年第一次弄的小型工程师访谈,今年2+1三场要豪华了很多,但是废话也多了很多。。。

===第二日===

Q:星际和风暴使用的技术为何如此相似?

A:星际的引擎一开始就是个面向数据的引擎,因此很适合开发不同风格的地图模式。风暴的雏形-暴雪全明星的起源就是一个星际组员工的闲暇项目。然后大家被吸引了,为此专门分了个小组,代码库也专门开了一个分支,但是有许多功能性代码依然是通用并且同步更新的。风暴目前也是类似的状态,即使看起来风格已经大不一样,但是背地里他们依然有很多代码是共享的,还有专门的GUI工具来转移需要共享的代码。

Q:WoW的数据真的很多,你们是怎么维护的?

A:讲真,真的很多。光是7.1的更新就导致了超过1000个表的更新,尤其是法术相关的表。有一个内部表格有超过两亿五千万行数据,有的时候想查这个表找些东西真是挺不容易的。内部开发的统一工具-WoW Editor经常要和数据库交互,操作起来会让人觉得WoW是这个数据库的图形化管理工具,而不是一个单独的游戏。

德拉诺的时候,他们引入了NGDP数据传输系统,在设计这个系统时,他们需要生成目前游戏里每一个文件的列表(内部文件,而非文件夹下的那种压缩大文件),光是为了做这个文件追踪系统就花了2年。新系统允许他们对于非常细微的内容进行改动(比如单个文件),也让HotFix的灵活性大大提高了。

Q:暗黑工程师要怎么解决大秘境fishing(就是看到大秘境地图不好或者怪物刷新不好就放弃)的问题?

A:这个问题有两个方面。他们首先检查了怪物的刷新机制。每个怪物对于进度的贡献取决于怪物的基础经验值,所以当前基于个数/区域密度的刷新系统是有很多问题的。新的系统会基于经验值密度,即保证每个区域里刷新的怪物的总体经验值,即对进度的贡献是近似的。

然而还有一个问题就是精英怪必须单独考虑。比如我们可以在一个区域刷很多的小骷髅,但是精英骷髅不可能也刷很多组(因为词缀导致的难度并不好预测),所以玩家如果看到这种情况依然会想离开。解决办法就是把精英怪的刷新独立在普通怪的刷新之外。这些修改在下周的PTR里就能体验到。

Q:守望引擎的优化?

A:守望使用了全新的引擎。从一开始,工程师就把所有平台都纳入了考量。游戏开发后期的工作主要都是引擎优化,使用了各种性能分析工具来评估CPU和GPU的表现。GPU的优化相对比较难,比如工程师有一次花了一天想去优化一个玻璃着色引擎,结果到最后一点提升都没有,因为GPU的调度器非常复杂,难以预测。

一个比较成功的功能就是渲染级别,尤其是主机上的动态渲染级别,能够根据场景复杂度实时调整,最终达到比较稳定的60fps。

Q:暴雪动画部门都怎么做那些渲染的?

A:动画渲染一直都是个很复杂的工作。在星际2的第一个CG里,泰凯斯所处的场景所使用的三角形,比当时整个wow所使用的三角形都要多。一开始动画部门只有15-20人,后来慢慢地涨到了200人。人多之后,可以有更多的人去负责专属的内容,比如动画师,比如粒子渲染,比如光照效果。

但是人多之后一个问题就是协作。某个部门发现的bug,可能要回溯到整条流水线上好几个部门之前才能找到解决方案,这样的流程是非常繁杂低效的。他们为此开发了一个工具叫做Aurora,把所有动画部门的数据集中到一起,并且提供了一个统一的交互接口。它本身底层是个C艹的属性管理系统,叠加了一层Python来整合商业以及部门结构的逻辑。夺魂之镰的CG就是这个系统管理之下的产物,效果很不错。

Q:如何解决科技债(即早期的开发没有预见性,导致后面开发越来越难)?

A:写个条子标记这是一个科技债,然后丢到一边忘记它!

好吧,认真说。很多时候设计师请求的东西,过几个月很可能就不需要了,同样的有的时候设计好的代码,可能要过很久才会得到利用。比如要塞相关的代码,在4.3末期就已经写好了,但是一直没找到使用的机会。因此只能说尽量提高设计的灵活性来预防。

另外一方面,对于内部代码的优化,往往不会被其他部门的人所感知,算是low-impact的项目,因此并不会作为重点目标。目前在做的一个就是在代码提交过程中使用了各种代码质量检查的工具,每次代码提交你都会看到整体质量下降或者上升了多少,然后督促码农去尽可能提高自己的代码质量。说到条子,他们的确花了很多时间去修复各种条子,也就是表单所反馈的因为老代码导致的问题。

Q:有没有什么我们不知道的严重bug是发布之后才发现的?

A:有也不告诉你(笑)。只能说他们为了避免这些问题进行了各种努力。Hotfix系统的进化,更简单的代码逻辑,复杂的QA测试流程,更灵活的发布日程,数据库级别的质量控制(避免奇怪格式的数据的插入),自动化等等。比如守望的一个自动化办法就是生成大量机器人(堡垒!)去地图里的每一个角落用一切可能的方式和地图疯狂地互动。

Q:聊聊服务器的架构?

A:他们有在密切关注类似Docker这一类比较新的解决方案。目前是混合云,由他们内部的私有云和AWS组成。AWS主要是为了美国以外的用户服务,提供数据传输一类的服务。最近也在开始尝试一些整合了AI的软件缺陷检测方案。

设计哲学来说的话,一开始各个大组(魔兽,战网,星际等)之间基本没有沟通,都是各自为战。几年前新的CTO提出了”One Blizzard“这个概念,强调了各个组之间的原生态协作,结果就是本来很多难解的问题和其他组沟通之后迎刃而解。比如风暴组提出来的新文件系统CASC现在已经推广到了所有游戏上。

Q:你们都是如何提升游戏表现(fps)的?

A:守望有用各种内部和外部的性能评估工具,检测各种参数,比如cpu/线程的利用状态,内存的使用效率等等。

这里还有一个轶事。美工开发模型的时候,都是以实际大小为准。比如一个石头消耗几百个多边形的话,一个高山可能就是几十万个多边形了。有一次某个QA在测试新场景的fps时,发现在一个桌子附近fps总会暴降,完全不知道为啥。最后他们发现那个桌子上的一个盆栽的树居然有数以万计的多边形:某个美工把一个海加尔树那么大的大树缩小了几百倍直接放到了盆栽里。结果引擎依然认为它需要把这十来万的多边形都渲染在这个小小的盆里,结果你懂的,可费劲儿了。

Q:星际的观战模式?

A:星际的服务器是状态锁定+同步的模型。服务器和客户端时刻交换大量的最新命令,以此模拟/同步最新的游戏状态。观战者想要看到最新状态,就需要拿到游戏开始到现在的所有命令并且模拟最新状态。并不是说办不到,只能说这里面有很多挑战。

Q:WoW的数据是怎么存储和分析的?

A:魔兽一开始的文件系统叫做Big File Folder(谷歌的GFS的梗),用不同的文件夹来存放不同的数据内容。为了不用每次都复制大量重复内容才能更新游戏,他们特地开发了专门的文件夹管理系统。目前是内容关联的文件追踪系统(Content-Addressable Storage Container,即CASC文件系统),存放了对应到内容的哈希值。在发布新内容时,这个系统让数据索引时间得到了大幅度的降低。数据库系统也是内部开发的工具。

游戏的统计数据定期会发送给BI(商业智能)团队,并且定期地得到分析团队的结果。开发者们就可以用这些分析来辅助决策。

Q:哪个方向的team人最多??

A:WOW组最多的人是gameplay组(游戏机制),这个组需要开发大量的游戏内部的新功能,每一个都需要可观的开发投入。战网也是个人很多的组,因为维护面向几千万玩家的平台和大量功能。守望里人最多的组也是gameplay组。

Q:工程师部门的性别比例??

A:80%男性,20%女性,目前的目标之一就是招到更多女工程师。

Q:给学生党一些进玻璃渣的经验?

A:保证课业的基础上,尽可能完成一些独立的项目(不过没人指望你solo个魔兽),是真真正正地完成一个项目,哪怕是俄罗斯方块也好。这个过程中需要的代码设计,系统设计,测试,debug能力都是暴雪所看重的。Unity相关的经验也是非常好的。

===第一日===

魔兽世界从一开始就有使用大量的隐形追踪目标来辅助触发各种事件。隐形小兔子就是一个著名的例子。比如巫妖王时期的远古海滩,战场的开始并不是你看到的倒计时。而是船上以及码头各自放置了一个隐形的对立npc,他们接近彼此后会开始攻击对方,一方死亡后就会开始战斗。类似的还有奥拉基尔的身边有几千个隐形漩涡,一旦玩家掉下平台并且撞到其中一个漩涡,就会被丢进一个又一个漩涡慢慢传送回平台,虽然在玩家看来就好像“飞”回去了一样。

这种手段其实很影响服务器性能,并且制造很多难以重现的bug。随着代码的改进,工程师们会尽可能不去使用这些有风险的手段,而且每个新副本都会专门评估下隐形追踪目标的使用量,因为过度使用说明设计有问题。但是时至今日也依然有很多机制是依靠隐形追踪目标来触发的。

要塞建筑完成时的动画里的3D文字效果真的就是3D模型,所以这个部分没办法本地化,只能依靠额外的字幕。军团再临里有个新系统可以把3D浮动文字加到游戏里,解决了这个问题。

军团再临的最大显示距离是原来的200%,部分高端机器上甚至高达300%。此外有一部分地标(比如萨格拉斯之墓)有着极大的显示距离,因为他们觉得能够让玩家从很远的距离看到这些地标会很酷。

WoW刚发售的时候,大部分用户都是单核,而且显卡也没有很多渲染单元。所以当制作组推出新玩家模型的时候,他们发现玩家模型的关节数量翻了三倍甚至四倍。模型动作系统还是当初单核的时候写的,不足以应对如此复杂的模型。于是他们加入了多线程支持,通过一个工作派发系统来让每个线程去负责一个模型的动作。然后制作组发现他们的模型复杂度又可以进一步提高了,算是解决科技债同时提高了引擎上限。在德拉诺的一些动画里,你会看到几百个兽人在动画里奔跑,这都依赖于模型系统的进步。

让玩家穿袍子时显示脚并没有技术限制,只是模型问题。夜之子的动作很少,所以可以避免脚从袍子里穿出来。但是玩家模型要复杂很多,脚的几何形状也可能随时改变,比如你穿比较大的鞋子时。

目前客户端内的游戏动画是被加密的,只有服务器解锁之后才能看得到。工程师想在基于文件的加密之上做到文件内部分段的加密,这是内部团队的共同追求之一。

玩家聚集的场景是很有挑战的。因为客户端需要知道其他人在哪里以及他们在做什么。所以游戏内同时显示玩家的数量是有限制的,以此来提高服务器性能,客户端性能,以及节省带宽使用。不过他们依然会尽可能提高区域内的玩家数量,以让你觉得这是一个MMO,而不是单机游戏。

施法时,客户端把会施法事件发给服务器,并且假设它会成功。所以有的时候你会看到施法成功,开始冷却,但是你却被打断并且没有效果。施法动画是立刻开始的,所以延迟高的时候你会看到你的双手在发光却没读条。这个设定是为了更及时的动作反馈。

类似寒冰箭这种读条法术,施法结束后UI可以马上进行反馈。但是瞬发法术你就需要等服务器告诉UI如何反馈,所以近战以前的手感很诡异,尤其是延迟高的时候。军团系统里近战的动画可以立即开始,然后真正的动作事件是服务器返回之后才发生的,所以动作事件和动作动画得到了同步,提升了近战的操作体验。

即便如此,法术系统依然有很多延迟信息要进行同步,也会导致很多并发冲突。

军团再临开服之前,设计师说为什么不通过一个酷炫的任务啪地一下把玩家传送到破碎群岛呢。听起来很棒对不对,结果工程师在各种实验之后发现现有的服务器技术无法支持,进而开发了新的动态切片技术来实时调整各个服务器的均衡能力。结果便是史上最顺滑的开服体验。

背包的问题在去年已经有过类似回答,http://bbs.nga.cn/read.php?tid=8700591。2016年的今天,默认背包系统最大的问题依然是如何保证各种写死的逻辑能够适应到新版本的代码,以及在重写之后如何迁移玩家数据,然后有这些时间一整个新补丁都做好了,想想还是算了吧。注:不过在后来的QA中已经提到背包问题似乎没有想象中那么复杂,也许会有解决办法吧。
大部分物品的20堆叠上限只是设计如此,并没有技术限制。
每个新资料片,工程师都会想办法解决一些科技债。
个人拾取的宝箱允许每个人都拾取一次,然而允许多个人拾取同一个宝箱其实挺难的,老的宝箱交互代码就是科技债的一个例子。

还有比如在德拉诺时,很多看起来不像箱子的物体,其实是作为箱子添加到游戏里的,导致了很多玩家交互的糟糕体验。现在有多人重复拾取机制之后就没有那么糟了。类似的优化一直在做。
剥皮无法共享是个老问题了。理想化应该是所有在怪物仇恨列表里的玩家都可以剥皮,然而短期内依然有技术限制。工程师希望将来可以修复这个问题。
在你的人物被跨服时,客户端会访问服务器重新请求一批应该显示在你视野里的目标,并且取消之前的显示目标。但是在最新地图上使用这种技术依然出现了很多不同步的状况,导致你的跨服体验不是很好,这一部分依然在优化。
同样的,在德拉诺开服时,出现了很多副本未找到的问题。这是因为负载均衡逻辑没有分配足够的服务器给你所属的副本群,而且你所在的副本群恰好最近不是负载很高的类型。他们在优化了负载均衡逻辑之后问题就少很多了。
Hotfix能做到的事情与日俱增是他们的目标之一。这个资料片刚开始的时候,因为hotfix太多结果产生了系统错误,他们甚至hotfix了hotfix系统本身的代码。还有一个常用的hotfix就是暂时性地启用更多log信息,以研究一些bug是如何产生的。

随着系统的进步,越来越多的代码可以放在服务器端随时修改,然后把修改推送给客户端,包括动画效果,美术效果,还有服务器和客户端的二进制码。即使现在已经可以用hotfix来增加新天赋也没有到他们满意的程度。最终的目标是让所有的非静态资源都能通过hotfix来进行修改。
水上坐骑有时无法工作是和碰撞模型有关的,尤其是玩家从水下移动到水面的过程。本来的碰撞模型非常粗糙,所以会出现侏儒明明在浮着却消耗氧气条,或者是人在猛犸坐骑上被认定是浮空这样的问题。

为了应对这些,玩家在坐骑上的碰撞模型并不是简单的玩家模型+坐骑模型+一定位移,而是有一套算法在计算最终的碰撞模型来触发环境效果,比如在游泳时你的碰撞模型其实不是紧贴水面,而是在水面下方一点,然而玩家的跳跃高度是固定的,所以你觉得你出水时的跳跃已经让你离开水面了,实际上你的碰撞模型可能还在水下,导致水上坐骑无法生效。这个目前依然不够完善。
一个类似的问题就是牛头人玩家经常被门卡住。牛头人的碰撞模型是比其他种族都大不少的,然而在竞技场里这个碰撞模型会被标准化成和其他种族一样,为了游戏平衡。
早期的反外挂系统之一是不断检测客户端告诉服务器的玩家移动速度,以及玩家实际的坐标变动。如果两者差距过大,服务器就会认为这个玩家在非法状态,并且尝试把他重新定位到合理的位置。然而这个系统却经常把合法的玩家重置到奇怪的地方,更麻烦的是要debug这个非常麻烦因为难以知道玩家在什么状态下触发了这个bug。

比如德鲁伊的职业大厅里有一滩水,如果你在某些坐骑上,你踏进去的时候就可能触发非法状态然后掉线。还有当初跨服刚开放的时候,有一个玩家总是在艾尔文森林和暴风城交界处掉线,工程师怎么样也没办法重现。最后他们只好复制了这个玩家的角色,发现他使用的一个跑速附魔在跨服时没有正确作用,结果把他带去了扭曲虚空。
你闪现时,服务器直接计算你当前位置+闪现距离+你是否可以到达目标位置来返回目的地。
你翻滚时,实际上是一个隐藏的跑速光环+暂时屏蔽玩家控制输入。
有一阵子鼠标提示会莫名消失,然后鼠标划过小地图的某个点的话又会出现。7.0之后这个bug不见了,虽然工程师也不知道到底怎么好的。。。就当是魔法吧!
一个良好的bug report应该尽可能描述你在那里,做了什么,什么样的状态,什么时间等等。不然工程师其实也很难重现你所遇见到的bug,更别说找到解决方案了。
每当有功能导致了很多玩家抱怨和表单,这些信息都会提交给工程师团队以尽快找到应对手段。
之前有玩家问为什么不用神器能量或者其他奖励代替目前的安慰奖金币,蓝贴回复说是因为目前的roll系统是mop时代做的,只能从boss的掉落表或者金币里选择一个。

然而工程师表示这个并没有技术门槛,而是设计师觉得”不可行“。类似的”不可行“的事还有不少,但是往往群众会先怀疑程序员,而不是设计师。[color=red]注:设计师在最近的访谈里已经表示这种安慰奖只是侮辱人,会进行修改。

UI里的锚点系统其实一度导致了非常多的浮点错误,所以UI材质里有很多偏移了半个像素。结果UI设计师不得不人工地去编辑XML,保证UI元素的对齐。

插件开发者和工程师经常交流心得和反馈。很多插件能让设计师意识到本来就应该在游戏里的功能。比如当初WoW刚发布时只有多个小队框架而没有团队框架。团队框架当初只是个插件,现在已经是基本体验的一部分了。

当然有时插件做的事情又太多了。比如工程师们把渲染地图标记的代码移到了C代码里,然后提供了API来让插件与之交互,但不让插件直接得到其具体位置。

试炼场和搏击俱乐部完全是设计师用WoW Editor(内部开发工具)做出来的,没有牵扯到工程师。

有些需要分位面同时作战的boss,会导致一组人看不到另外一组人的战斗数据。工程师起初尝试让玩家只是一部分的状态切换到不同位面,还有一部分可以继续得到全局的战斗信息。最后在实际游戏里出现了不少奇怪的位面问题。

炉石的卡牌逻辑都是在服务器端,客户端做的只是请求服务器下一步应该显示什么样的结果。因此对于卡牌的修改是非常方便的,比如产生随机法术这种逻辑,在服务器那边也不会需要用很复杂的脚本就能写出来。

炉石服务器端的脚本语言最近被用C艹重构过一次,并不是为了运行效率,而是为了降低使用的复杂度。

炉石早期的移动开发人员本来都不是游戏开发,而是其他组的各种移动应用和服务开发人员组成的。

守望先锋里判断玩家的战斗力并且寻找队友的逻辑,一开始只是很简单看你的击杀,然后为了照顾其他类型的英雄增加了越来越多的逻辑。一开始也只是很简单的快照值,并不是总看你的动态表现,但是慢慢也在改善。

blizzcon的售票系统牵扯到了很多分布式系统设计的挑战(分布式消息队列,公平性,负载均衡等),最后的解决方案反而非常简单粗暴。服务器只维护当前剩余票数和当前在购买页面的人数这两个值的一致性,同一时间里只有一小部分用户可以真的访问购买页面,其他人都只能转圈。(然而如何公平地选择这一批用户,似乎他们并没有很好地解决)

暴雪的程序员对于一些细微内容的添加与否有很大的影响力。比如他们可以觉得某个小角色很coooool,反馈给设计师,然后设计师很可能就会说”为什么不加进去试试呢?”。当然不太合理的请求还是会被设计师拒绝的。