本文为《死亡细胞》主设计师Sebastien Benard去年在Gamasutra发表的一篇探讨“随机性”和“可玩性”如何平衡和实践的文章,原文地址戳这里。个人觉得他们在制作《死亡细胞》过程中总结的这一套方法论还是很有参考价值的,对于想做RogueLite游戏却无从下手的开发者也很有启发性,是比较难得的干货文章。
大家好,我是Sebastien Benard,目前在《死亡细胞》担任首席设计师,《死亡细胞》是一款由程序生成关卡的Metroidvania类游戏。
最近玩家和其他开发者询问了我们很多程序随机生成关卡质量相关的问题,也难怪,最近关于游戏中程序生成和随机性的讨论甚嚣尘上(我:可能是无人深空的锅)。玩家们对程序随机生成的怀疑态度也是情有可原,况且Metroidvania类游戏在人们印象中,核心就是设计师们一丝不苟小心翼翼设计的关卡。好吧,接下来就让我来回答大家的怀疑,并深度探究下我们是如何在Metroidvania类游戏中加入roguelite可重复游玩元素的。如果你更喜欢视频而不是读长篇的文字,我们为你准备了一段“精炼”版本的开发日志视频。
(我转载到B站了,不过并没有字幕,想看的戳这里)
在介绍具体步骤前,我想聊下我们为什么想把程序随机生成这一因素加入到Metroidvania这种需要精细关卡设计的游戏类型里。
两年前,当我们开始做《死亡细胞》的初版原型时,我们遵循了传统的、手动制作关卡的方式。但问题接踵而至,我们很快发现按照这样的制作速度,考虑到团队的人数和规模,做完和打磨好这款游戏显得遥遥无期。
至此之后我们知道必须得寻找一个Plan B。在做《死亡细胞》前我们开发了很多网页游戏,大部分都包含了随机元素和程序生成的特点,所以我们算是比较熟悉程序随机核心概念的。除此之外,程序随机生成也被应用到很多叫好又叫座的游戏里:《以撒》、《Minecraft》、《Starbound》等等。受这些游戏激励,显而易见,我们觉得至少得做一个原型,检测下随机性和《死亡细胞》的化学反应。
原型很成功,在永久死亡机制之上带来了更多的可重玩性。一个更深刻的变化是,我们发现这个原型从基础上改变了游戏里的战斗感觉。将战斗的重点放到玩家的随机应变和反应上,而不是通过机械背板来过关。总而言之,这个原型的感觉很棒。
但是,也存在一些问题,尽管随机刷新敌人提升了核心游戏性,但关卡设计遭受了重创。简而言之,随机关卡显得混乱没有条理,让你无法感受到整体性,也没法沉浸到游戏世界中去。
即无法完全手工设计关卡,也不满足于完全由程序生成关卡,我们觉得需要寻找一个折中的方案。
这里我们得谢谢《洞穴探险Spelunky》团队,他们也面临过相同的问题,并提供了一些有趣的解决方案。如果你有兴趣的话,可以戳这里简单了解下(需要梯子才能看)。总而言之,他们把手工制作关卡和程序生成混合在一起,让关卡同时具有多样性和持续性。
在讲具体的技术实现细节前,我还想提两个让《死亡细胞》深受启发的游戏。
第一个是《Faster Than Light》:即拥有程序生成的随机性,也拥有精心安排的情节和统一的宇宙世界观。我们认为它是这类游戏的标杆。
第二个是《求生之路Left For Dead》,哈哈,是不是没有想到。最开始的时候,《死亡细胞》原型是一个僵尸塔防游戏,我们从《求生之路》的底层理念学习了不少东西,Valve为了解决重复游玩性构造了一个AI Director系统,可以根据每局不同的情况随机摆放普通和特殊僵尸。你可以戳这里了解下基本概念,还是很有意思的。
我们开始做自己的AI Director系统,虽然那时候八字还没一撇,但我们确立遵循一个最基本的原则:这个系统构造关卡时,要围绕穿插紧张刺激和放松奖励的流程,来确保游戏节奏错落有致,从而让玩家无法自拔。
总结下我们的目标:创建一个融合了程序生成关卡的世界,具有变化多样性和重复游玩价值,难度建立在玩家对一个持续变化关卡的反应而不是背板上。与此同时,还必须在关卡和流程中保持一致性,融入世界观。汲取之前游戏的经验,经过很多次的尝试,失败,调整和不计其数的微调后,我们总结了六大步骤,希望能作为帮助你实现高质量程序生成关卡的基础。
-
首先,我们确定好固定的元素,在这个框架内程序生成才会施展拳脚。整体的世界地图设计,不同关卡之间如何连接,解锁下一个关卡的钥匙位置等等。不管游戏的随机数种子如何变化,这些元素都是手动设计,不会变化的。
-
接下来,我们手动设计了一系列的房间块,每个房间依据其配置项,可以充当不同的用处。下面是我们在软件CastleDB中建造的一些房间示例。
实践中,每个房间块的地形结构都是为其用处而专门设计的。藏有宝箱的房间和商人房间构造不同,而这两种房间又和战斗房间结构差别巨大。每个房间的属性主要包括入口数量,是否有出口以及房间的用处。
每个房间还从属于某个大关:比如在监狱房间块就不会用在下水道场景中。这样确保每关有自己的特色——比如下水道场景都很狭窄,限制了跳跃和回避的作用,迫使玩家合理安排他们的操作。
-
好了,既然有了一堆还算可以的房间块,现在需要把他们用合理、有趣的方式安排起来。我们为每个大关创建一张概览图,用抽象节点表示房间块,显示出其中房间块的数目和连接顺序。先添加关卡开始节点和出口,然后添加一些特殊房间(宝箱,商人等等),最后在之间添加探索和战斗的房间。
这张概览图作为下一步的程序生成算法的指导性基础,定义了关卡的长度,特殊房间的数量,关卡的复杂度等等。每个大关都有张独立的概览图以保持其风格统一。比如比起下水道关,我们让壁垒关更线性,流程更直接。 -
在我们把这些条条框框和设计上的约束准备好之后,我们的程序生成算法终于要登场了。对于每个房间块节点,程序在该大关的候选房间中随机选择一个房间,并检测是否符合概览图中的要求(入口位置,入口数量,房间类型等等)。如果不符合,程序会重新尝试另外的房间直到找到符合要求的。大功告……等等,还有事情要做。
-
玩家需要敌人来进行战斗。每关的怪物数量是由每关的战斗房间的战斗Tile块(我:这里应该是每个战斗房间标记了放置怪物的战斗Tile块)决定的,举个随机的例子,在程序生成的下水道关中有250个战斗块。我们先定义每个战斗房间中出现怪物的数量,比如每5个战斗块出现一次,那整个关卡中就要放置50个怪物。
每种怪物也有自己对应的属性和限制,比如有些更危险的怪物每10个战斗块出现一次,有些精英怪一整关都不能出现超过一次,有些不能和其他某种怪物一起出现,有些则需要在有较大空间方便移动的地方出现,等等不一而论。 -
最后一步就是生成金币,细胞核心和掉落物。
好了,经过上面的长篇大述,我们分享了自己的方法,希望有人能汲取些有关程序随机生成的思路。我也希望其他开发者们能敢于冒险勇于尝试——像融合两种看起来毫不相干的想法和思路。有时候会有奇效。
Cheers!