成为现象级产品不是偶然的,从这些技能设计的深入推敲我们能够略见一二。
对于动作类、MOBA类游戏而言,技能的设计至关重要,技能设计的好坏通常直接关系到游戏体验乃至产品成败。然而真正能够把技能设计细化到单独一套“弹道体系”的游戏则凤毛麟角。作为行业翘楚的《英雄联盟》在最近一次更新中,彻底重构了“弹道技能”体系的代码,从各方面重新优化了设计。
Riot Games也在官方技术博客中分享了此次优化的经验,包括“弹道技能”旧体系层级分类和新系统设计的理念等。从中我们能看到《英雄联盟》开发团队对设计细节的把控、对表现标准的要求都十分到位,这当然也是游戏能够成为同类标杆的重要原因。葡萄君编译了博客全文,希望对做类似设计的从业者有所帮助。
新弹道技能体系的来源
各位操作娴熟的召唤师,大家好。今天我们来谈一谈飞弹——或者说弹道技能的一些技术基础。过去的几个月里,我们对《英雄联盟》(下简称LOL)中的弹道技能做了一系列改动(见本段后)。当然如果我们的工作做得到位,玩家在游戏中是体会不到明显变化的。不过虽然表现不明显,这次的技术改动还是让我们有不少收获,也为后续的一些设计内容提供了可能,所以我们想分享一些更深入的内容。
从技术角度来讲,其实说来话长。我们梳理后台代码有一段时间了,近期的目标是“线性弹道技能”这个具体方向。你可以把它理解成有投射轨迹的飞弹,比如伊泽瑞尔的Q/W/R都是这种线性弹道技能,而他的普通攻击则不是。在我们讲具体细节之前先说一些改动:这次重构代码旨在解决两个问题。一是修复某些弹道技能会直接穿过单位的bug;二是技能的击中判定应该是基于单位碰撞体积而非模型的中心点。
伊泽瑞尔的Q技能“秘术射击”和普通攻击
但描述弹道技能和用代码实现弹道技能之间有非常大的差距,各式弹道技能的设计也是不同的,这是问题所在。
我们虽然专注在一些代码的工作上,这些改动能修复很多问题,但不是所有。比如有时候看上去是弹道技能可能只是一个抛射的小兵——就像辛德拉的技能那样。这是我们第一次优化弹道技能的代码,很多尝试还不是最终解决方案。
辛德拉的技能“驱使念力”
之前旧的代码体系很混乱而且难以调整,而新的体系能够让我们实现很多有趣的功能,比如这样:
当然我们不是要把技能做出这样,只是展示一下在当前的代码体系下我们能过达到的效果。
LOL复杂的飞弹分类体系
你可以放大这张图,但就像电子音乐不重歌词那样,我们想要强调的并不是其中的文本,而是宏观的结构概念
游戏中的弹道技能不像导弹引导系统那样复杂,但一些复杂的飞弹运动方式还是让改动变得有风险。简单来说,这张结构图是我们划分出的弹道技能分层,不同部分对应不同技能的飞弹类别。这些不同类别的功能性有时是共享的,有时候则是直接复制的,还有更多时候让人觉得很混乱。通过整合相近功能性颜色代码,这张表从水平的角度打散了这些飞弹类型。比如说,如果你想要了解弹道技能飞弹的碰撞追踪,你需要逐一浏览这些标成粉色的代码,它们分散在这张表的各处。
图标最顶端的位置是我们称之为“基础飞弹”的部分,它们是这些分级的最底层、也就是游戏里最简单的飞弹类型。具体来说就是:这种飞弹会飞向某个位置或某个单位,只有当飞行过程结束时才会生效。(远程)自动攻击、防御塔攻击都属此类。在技能中,库奇的Q、吉格斯的R技能也是同理,它们的飞行方式简单直白——追踪目标、然后判断飞弹的指向地点、之后判定是否击中,没有其他额外的元素。
库奇的Q技能“磷光炸弹”
吉格斯的R技能“科学的地狱火炮”
下一个比较大的部分我们称之为“线性飞弹”,也就是通常玩家口中的“非指向性技能”。比如伊泽瑞尔的Q/E/R技能。但这其中有一些让人意外的地方,亚索的风墙(能阻挡敌方的弹道技能)也属于一种线性飞弹技能,这听起来有点讽刺。
伊泽瑞尔的Q技能
亚索的风墙“风之障壁”
线性飞弹的运行逻辑要比基础飞弹复杂得多。举个例子,有的技能会在飞弹运行中击中目标、随后返回施法者(比如德莱文的大招),也有的会像像落地生根那样留在地表(比如婕拉的“缠绕之根”)。那么把这样诸多的行为逻辑都归于一个体系中显然是不妥的。但从另一个角度来说,线性飞弹其实是基础飞弹的衍生体系。所以线性飞弹继承了基础飞弹所有的功能,但通过不同的方式表现了出来。这就让我们在优化整体弹道技能的时候面临了一些风险,因为一旦我们调整了基础飞弹,线性飞弹的体系就有可能崩溃,崩溃的形式也可能多种多样。
德莱文的大招“冷血追命”
婕拉的“缠绕之根”
图表的底部是我们称之为“环形飞弹”的部分,比如戴安娜的Q和W技能、阿狸的W技能,这些技能的运行方式类似于线性飞弹技能,只不过是呈环形运动的。它们同样源于基础飞弹技能,而它们的击打方式则与线性飞弹一致,当然运动方式和二者都不同。绘制这张图表的时候我们发现,在线性飞弹中修复的bug也同样从环形飞弹中消失了。可见原来的设计在复制代码的同时也复制了这些bug,这也是我们对“复制粘贴”这种事需要警醒的。
戴安娜的Q技能“苍白之瀑”
阿狸的W技能“妖异狐火”
嗯,这只是个比喻
简单来说,LOL中的弹道技能系统原本很复杂,内部错乱纠缠(就像一盘意面一样),而且比较脆弱。但弹道技能是游戏中非常重要的一个部分,我们必然要想办法优化整个繁杂的系统。所以我们用nuke彻底重写了系统,从最底层、最基础的部分开始,这样我们才能规避此前哪些问题。
重构弹道系统代码
关于重写弹道技能系统我们总结出了4点核心原则:
-类功能要在代码层面体现出来以避免误解。
-不同功能组之间的相关性应该被最小化同时要显著地标明。
-推理论证飞弹的行为逻辑不应该成为困难。
-把那些特殊的行为方式从常规方式中干净利落地剥离出来。
我们团队列出了一个清单,清单的项目主要是“弹道技能的飞弹会做什么”。团队计划在重构代码的过程中逐一突出这些项目,这个清单如下所示:
-移动:飞弹会抵达某些地点。
-击打:飞弹击中物体。
-目标追踪:飞弹飞向可移动物体。
-脚本界面:设计师具体设计飞弹如何运动、击打等。
-可视性:飞弹可以被某些人/物体看见,而对其他人或物不可见。
-音画效果:通过这些来表现到底发生了什么。
参照这个名单我们开始重写整个弹道技能系统的代码,每一项都针对飞弹运行构建了相应的元素。随着设置工作的深入,我们会不断地重新评估各个分支,并且在抽象概念不能实现目标时适时作出调整。举个例子,我们把目标追踪的逻辑融入了到移动相关的代码中,因为我们发现他们有很强的关联性。我们还把脚本界面融入到了飞弹的基础层面,因为我们发现没有必要在不同飞弹之间做这类区分。最后我们做出了这样一个弹道系统,图表化的表现形式如下所示:
我们将第一个图标称之为“彩虹一样的呕吐”,而这个就只是“彩虹”
弹道技能优化对LOL意味着什么
当相关工作都结束、开始总结的时候,我们发现了两个最显著的收益。首先飞弹相关的代码不会再给我们的程序员带来困扰了,bug等缺陷现在变得易于追踪和修复。考虑到有些缺陷此前长期无法修复,当前的解决方案已经看到了比较实际的好处。
比如说有展示飞弹直穿单位这类bug的视频,我们曾经对着这些视频一脸懵逼找不到原因。在一些非常罕见的情况下,这些bug出现时会从深层次上影响游戏。但当时我们完全没有办法重现这个问题或是思考任何解决方式,只能暂时搁置。不过把所有的飞弹碰撞(的场景)整合到一起的时候,一些情景会使得碰撞失效,这时候会更利于观察分析。梳理过这些内容之后,我们对设计飞弹命中目标、命中方式有了很高的自信。
当然,尽管我们修复了诸多的bug,弹道技能的飞弹直接穿过单位的情况或许还会出现。不过我们认为,以后类似案例的原因可能更多是出于单位位置同步上的错误,而非弹道技能碰撞判定的问题。
其次,除了减少缺陷、减轻对程序员的折磨之外。第二点、也是更重要的一点收益——就是我们在弹道技能设计的发挥空间更大了。有了新的体系之后我们不用再重复以前繁琐的过程,即为了一种运动方式不同的弹道技能专门做一个飞弹的分类出来。现在我们可以更随意地做一些疯狂的设计。下面的一些gif图就是很好的例子,当然这只是举例说明我们能做到,并不代表我们要在游戏中实装。
德莱文的飞斧可以在空中自动攻击:
维鲁斯的攻击方式也可以调整成这样:
让艾希射出一个六边形:
这些都是可以实现的功能。