游戏邦在:
杂志专栏:
gamerboom.com订阅到鲜果订阅到抓虾google reader订阅到有道订阅到QQ邮箱订阅到帮看

Tanya X Short分享程序生成关卡设计经验

发布时间:2014-02-08 16:33:54 Tags:,,,

作者:Tanya X Short(Kitfox Games创意总监)

引言

我的职业和背景是关卡设计师,我会做系统设计、游戏设计和故事设计,但我的内心实为一个内容设计师。无论是在《The Secret World》中的Lovecraftian低语,还是《Dungeons of Fayte》中的煤泥,我的最大乐趣几乎都是来自创造手工玩家体验。所以当Kitfox决定以小团队身份角逐竞争日益激烈的市场时,我们将投入程序生成内容领域时,我最开始有一点紧张。

程序生成的一个危险在于,你有一部分完全相同,其风格和特点基本上是可预测的内容。程序生成的唯一优势就在于其“表面内容”是不可预测的。本文主旨是回顾我们如何避免这一问题的做法和经历。

首先我要讲讲我们的数据结构,我讲简要谈谈我们如何使用Unity来创造设计师“工具”,并展示其复杂性如何在一个简单的前提下自然发展。记住我是一名设计师——我并不是在编写《Shattered Planet》中的一代程序生成代码。所有对编程感兴趣的程序员应该直接去向Mike Ditchburn、Jonwoo Kim和Greg Londish求教。

pocgen3(from gamasutra)

pocgen3(from gamasutra)

作为设计师,我的职责是定义计划好的玩家体验,并与程序员合作将其转化为便于游戏引擎遵循的可行规则。与此同时,团队中的美术人员Xin Ran Liu会同我合作使用这套相同的规则,从模块生成具有美感的场景设计。所以我们在此更注重观察系统背后的逻辑,而不是运行系统的代码,或者它所用来渲染的精灵。

现在让我们进入正题吧。

目标

我们是在2013年6月开工。经过两周之后,我们完成了小小的原型,我们的玩法实际上是拥有程序生成关卡的回合制RPG。我们知道自己可以命名用Unity。

不久之后,我们决定用3个设计准则来引导我们所有的设计决策(也具有一些美术方向的影响):

*有趣:激发玩家的好奇心,并奖励他们的试验和探索行为。

*战略性:奖励战略性玩法——用不同的方法来获得战斗上的优越性,从而产生困难的决定。

*易用性:即时吸引力,大量反馈,鼓励和可选择的信息。

当然,如果过于偏重某个方面或对之使用不当,每个原则都会产生自身风险。如果“有趣的”内容过于神秘,玩家可能就看不到,或者完全为之所困。如果战略性元素过于强大,这可能就会令玩家不快或者吓倒他们,尤其是在平板电脑上(除除我们要虏获的是自相矛盾的粉丝)。另一方面,没有战略性或神秘感的易用性,则会让人觉得游戏是一个没有趣味的空壳,对于像我这种硬核玩家来说尤其如此。

但在创造关卡之前,你得先创建模块。

房间结构

我们想从网络上学一些关于程序生成游戏关卡的内容。其中多数信息包含从贴图式、矩形“房间”和“走廊”拼接而成的“地下城”。我们尽量阅读和吸收这些知识。但是,为了保持那种“Shattered Planet”的感觉,Xin从美术角度进行指导,这样我们的房间在外观上会更加自然。这很棒,但这样也让我们无法使用他人的算法。

所以我们给每个房间分配了最小和最大高度和宽度,使用方形贴图。例如,最小的房间可能是2*2,最大的则是4*4。这就产生了多种大小的房间规格。以下就是我用于确定房间大小可能性的设计工具(每个关卡集拥有4-5个房间定义):

roomdata(from gamasutra)

roomdata(from gamasutra)

(注意,从情境上看并不明显:最小和最大的“房间数量”实际上涉及同一关卡中允许出现多少个这一特定的房间定义。

作为关卡设计师,我选择了不同的房间大小来产生玩家的不同情绪反应。小房间(2*2)或者Lake房间更具幽闭恐怖症的特点,但也同时允许玩家采用更有策略性的手段来战胜AI(令其在走廊被阻拦或被封闭)。相反,更大的房间则更为开阔并充满潜力,但也可能导致玩家陷入四面楚歌的境地。确保不同关卡拥有不同风格(紧凑或松驰)可以保持算法的不可预测性。

以上所述就是一个来自“RoomsBasic”关卡集合的小片段,与“NoLakes”关卡集合相反。)

使用这些宽度&高度&湖泊规则可以产生以下结果:

level-generation-design(from gamasutra)

level-generation-design(from gamasutra)

如你所见,每个房间也有可能产生内部“洞穴”,或者“湖泊”。这完全由引擎来处理——作为设计师,我不过是指明某一房间是否含有湖泊。根据主题(例如,沙漠、实验室等)的不同,“湖泊”可能看起来像水、激光、迷幻药等。我还可以决定贴图房间应该使用的各个主题(尘土和灌木丛?或者石头和草地?或者二者的结合?),以及其中的障碍物(游戏邦注:岩石、蘑菇、结合体等)。以下是另一个工具截图:

themedata(from gamasutra)

themedata(from gamasutra)

(Gen Dirt=普通尘土,Des Sandstone=沙漠砂岩,StoneDort是一半尘土,一半砂岩,这自然形成了一个介于主要与次要贴图类型的边缘)。

除了潜在的“门”贴图外,每个房间还有2-4个贴图集,每边一个。当它们与其他房间连接起来时,游戏就使用一个寻径算法来确定布置障碍的合理性——例如,在哪个地方无法阻碍玩家穿越该房间或找到宝藏。

obstacles(from gamasutra)

obstacles(from gamasutra)

所以,根据这些房间以及我的传统关卡设计经验,我们针对关卡如何生成这一问题创建了最初算法,这一切都关键路径(Critical Path)有关。

关键路径

如果你是一名关卡设计师,你知道“关键路径”是玩家为了无成关卡的必经之路,其中没有任何旁支轨道、干扰或灾祸。一般来说,为了鼓励玩家继续走在“正轨”,设计师要提供诸如钱币等奖励,但其中也不乏敌人的身影。这看似有违人们的直觉,但假设战斗很有趣,并且是你游戏的中心特征,玩家就会期待参与战斗。这会推动玩家持续前进。

所以在《Shattered Planet》中,我们所创建的关卡生成的首要规则之一就是引擎要能够确立房间的一个“关键路径”,其中包含玩家的起始“房间”,最终的“传送”房间(玩家逃离该关卡的所在),并且所有的房间都直接相关。以下是我在2013年6月手动创建的一个模型,以此向程序员传达我的设计意图:

critical path(from gamasutra)

critical path(from gamasutra)

我们之后将这些视为与不同于旁支房间的房间。当关键路径房间获得了大量钱币堆引导玩家前进时,旁支房间就会获得“财宝堆”——更少但更大的钱币堆。与之相似,当关键路径房间存在难度一般的怪物时,走向旁支房间可能会遇到难度更大的怪物。这可以创造一种风险奖励之感——一般来说,走向与大反派相反的方向可能会找到传送器,但也会因此错过宝藏。

所以在这一点上,如果没有进一步的提升,它在编辑器中的地图就会像下图所示。你可以看到第一张图中含有一些美观的装饰物,例如疏松的贴图和之前提到的半贴图转变效果,而底下两图则是更早之前的版本:

pocgentriptych(from gamasutra)

pocgentriptych(from gamasutra)

上锁的门

为了增加一点多样性和探索角落的理由,我们增加了上锁的门,在关卡四处分布开门卡。我们决定令上锁的门作为玩家的可选项(能够获得宝藏奖励,当然也会遇到怪物),而不是令其成为阻碍玩家进展的必选项。所以,我们想确保上锁的门永远不出现在关键路径。由于我们知道哪些房间位于关键路径,所以就很容易暂时移除某个非关键路径房间的走廊:

我们仍然需要在其中植入一些算法优化,以便仅其呈现自然感觉。我们想确保诸如上锁的房间具有更高的额外宝藏机率等设计。

desert(from gamasutra)

desert(from gamasutra)

替代路径

我们几乎是在关键路径和旁支房间布置好之后,才意识到游戏关卡极其无聊。它们有大量死胡同,这会导致许多迂回寻踪行为,对寻找宝藏的人来说尤其如此。事实上,在以上地图中,一个房间最多只能容纳2个出口。这并不是很丰富的选择。

所以为了增加多样性和“流动性”,我们在关键路径和旁支房间布置好之后,添加了房间的连接性。还记得在“房间结构”环节我提到的我们如何为每个房间规划“门”的内容吗?我们要再次使用这一方法!我们找到彼此想念的两个门,在两者之间画了一条直线,在必要时令其向右转。

junction(from gamasutra)

junction(from gamasutra)

这为死胡同问题增加了新鲜感,令玩家的探索更加有趣。

异常处理

与任何规则一样,这里也有一些异常处理。尤其是在游戏设计中。

虽然我们游戏的多数内容是程序生成的,我们还需要支持一些“手工创造”关卡,其中包括作为玩家中心的太空飞船,以及其他神秘关卡、boss战斗等。我们试图尽量重用相同的数据。所以针对贴图,我使用了以上述例子相同的TerrainData立方体——以下是我取自一个普通贴图的截图,并以之前熟悉的“Gen Dirt”取而代之。

tilehub(from gamasutra)

tilehub(from gamasutra)

我还可以设置普通的敌人、道具和用于布置主题的障碍数据对象。

我们还需要根据向游戏添加的能量不时进行调整。例如,当我们添加了“点火”机制时,我们令自然的贴图类型(草地、灌木、苔藓)成为易燃物,以便火焰自然蔓延。所以我们现在有了一个场景设计规则,除非有极特殊的理由,不然玩法场景都应该能够出现自然贴图。当然,自然贴图VS非自然贴图的比例变化幅度甚大,可以看情况增加/减少有用之物和危险之物,并挑战玩家即时更改策略的能力……但如果火焰仅适用一个场景,那它就会成为非常无效的机制。

无论你何时在玩家工具箱中添加新工具,都要进行相似的调整和异常处理——瞬间传送、跳跃、伪装、潜行、隐形等。假如你想让该能力以一种灵活、用户导向的方式呈现真正的用处,你的关卡设计算法就要考虑到这一点。

未来变化和获取经验

《Shattered Planet》关卡设计几乎完工了,但我们想用一些替代传送器让玩家跳跃到特殊/神秘关卡主题,让玩家创造性地制作自己穿梭于各个房间的路径,甚至还可以让他们拥有游泳的能力。

如果说我们从过去向个月的试验中学到了什么经验的话,那就是:

*要灵活运用传统关卡设计原则——它们仍然很管用!

*程序生成需要大量的测试!仅仅是找到如何复制一个漏洞的方法,就可能花上数小时加载和重载时间来隔离那些作弊的算法环节。

*在你“完成”执行程序生成时,要保持开放心态对待可能存在的提升空间。与其他设计层面一样,你可能永远也不能算是“完工”。(本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦

Level Design in Procedural Generation

by Tanya X Short

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.

The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

Tanya X. Short is the creative director of Kitfox Games. A version of this article was originally published on the Kitfox Games blog. Any and all relationship between this article and their new game, Moon Hunters, is pure speculation.

Introduction

I’m a level designer by trade and training. I’ve done system design, game design, and narrative design, but my heart is that of a content designer. Whether it was Lovecraftian whisperings in The Secret World or friendly slimes in Dungeons of Fayte, I seem to get the most joy out of creating hand-crafted player experiences. So when Kitfox decided that, as a small team looking to compete in an increasingly crowded market, we would invest in procedurally generated content, I was initially a little nervous.

One of the dangers of procedural generation is that you end up with a smooth blend of samey content that’s essentially predictable in flavor and tone. The singular advantage that proc-gen has over “couture content” is unpredictability, so it’s essential that this not become diluted. This article is a retrospective, reflecting on how we tried to avoid that trap, and made me glad we decided as we did.

I’ll talk a bit about our data structure, I’ll show a little bit about how we use Unity to create designer “tools”, and demonstrate how the complexity grew quite naturally over time from a simple premise. Keep in mind that I am a designer – I didn’t write a single line of the procedural generation code in Shattered Planet. All programmer high-fives and awe-struck eye-shinings should be directed towards Mike Ditchburn, Jongwoo Kim, and Greg Londish.

pocgen3

As the designer, it’s my job to define the intended player experience, and work with the programmers to translate that into workable rules for the game’s engine to follow. Meanwhile, Xin Ran Liu (the artist) and I worked together to use those same rules to generate aesthetically pleasing environment designs from modular pieces. So this is a rather high-level look at the logic behind the system, rather than the code that actually runs the system, or the actual sprites it uses to render it.

If you’re interested in the actual code, let us know and we’ll see what we can do!

So without further ado… let’s start at the beginning.

The Goal

We started work in the beginning of June, 2013. After two weeks, we had finished with our little prototype and we our gameplay was essentially a turn-based RPG in procedurally generated levels. We knew we would be using Unity.

Not long after, we decided on three design pillars to inform all of our design decisions (with some art direction impact as well)

* Intriguing: entices the player to be curious, and rewards experimentation & exploration

* Strategic: rewards tactical play — various different ways to achieve combat superiority, resulting in difficult decisions

* Accessible: immediately engaging, with lots of feedback, encouragement, and opt-in information

These each, of course, had their own risks if any one aspect became unbalanced or poorly implemented. If the ‘intriguing’ content is too mysterious, it may be invisible to players, or downright bewildering. If the strategic component is too strong, it may be off-putting or intimidating for players, especially on tablets (unless we think we can subsist on poaching Paradox fans). On the other end of the spectrum, if there’s accessibility without strategy or mystery, it will feel like an empty shell of a game with nothing worth engaging with in the first place, especially for more hardcore gamers like myself.

But before you have a level, you need the building blocks.

Room Structure

We wanted to be able to learn from the reams and reams of information online about procedural generation of game levels. Most of these involve “dungeons” assembled from tile-based, rectangular “rooms” and “corridors”. We read and absorbed these as much as we could. However, to keep with the “shattered planet” feel, Xin directed that from an art perspective, it was essential that our rooms would be more organic in shape. This is cool, but made it so we generally couldn’t use someone else’s algorithm. (Though a few months later, someone wrote this neat cave generator.)

So, we give each room a minimum and maximum height and width, using square tiles. For example, a room might be a minimum of 2×2 but a maximum of 4×4. This results in a variety of possible sizes. Here’s an actual shot of what my design tool looks like, for determining the room size potentials (each level set has 4-5 room definitions):

roomdata

(Note, since it’s not obvious from context: Min and Max “Num Rooms” actually refers to how many of this particular room definition are allowed to appear in a level.

The level designer in me chose different sizes of rooms to cause different emotional reactions in the player. Small (2×2) rooms or Lake rooms are more claustrophobic, but also allow more tactical maneuvers to overcome A.I., by blocking and trapping them in corridors. Conversely, larger rooms feel more expansive and filled with potential, but also can cause the player to become surrounded on all sides. Ensuring that different levels have different feels (tight or loose) keeps the algorithm unpredictable.

The above is a snippet from the “RoomsBasic” level set, as opposed to the “NoLakes” level set, etc.) Using those width & height & lake rules results in something like this:

level generation design

As you can see, each also has the possibility of internal “holes”, or “lakes” to be generated. This is handled entirely by the engine — as the designer, I merely specify whether or not a given room can have a lake or not. Depending on the theme (desert, laboratory, etc), the “lake” may look like water, lasers, acid, etc. I can also decide per-theme which tiles rooms should use (Dirt and brush? Or stone and grass? Or a combination?), and which obstacles (rocks, mushrooms, a combination, etc). Another tools screenshot:

themedata

(Gen Dirt = Generic Dirt, Des Sandstone = Desert Sandstone, StoneDirt is half of each, naturally forming a border between the primary & secondary tile types)

Each room also has (thanks to our lead programmer, Mike Ditchburn) 2-4 tiles set aside as potential “door” tiles, one on each side. Once these are actually connected to other rooms, the game uses a pathfinding algorithm to decide where it’s “safe” to place obstacles — i.e. where it won’t block the player from traversing the room or accessing treasure.

obstacles

So, taking these rooms and my experience in traditional level design, we built the initial algorithm for how our levels would be generated, which was all about the Critical Path.

Critical Path

If you’re a level designer, you know that the ‘critical path’ is the way the player MUST go, in order to complete the level, with no side-tracks, distractions, or mishaps. Typically, to encourage players to continue on the ‘correct’ path, designers place rewards such as coins (similar to an enticing trail of Reese’s Pieces)… but also enemies. This seems unintuitive, but assuming combat is a fun, central feature of your game (i.e. not a stealth game), players look forward to an opportunity to engage with your combat. This pulls the player forward.

So, in Shattered Planet, one of the first rules of level generation we established was that the engine would establish a “critical path” of rooms, which contains the player’s starting “room”, the final “teleporter” room, where the player escapes the level, and all rooms directly in between. Here’s a hand-built mockup I made in June 2013, to communicate my design intent to the programmers:

criticalpath

We then treat these rooms differently than side-rooms. Where critical path rooms get lots of little piles of coins to lead the player forward, side-rooms get “treasure piles” — fewer but larger coin-heaps. Similarly, where critical path rooms get fairly average-difficulty monsters, wandering off to the side-rooms may result in occasional monsters of greater difficulty. This is supposed to create a sense of risk for reward — generally, going the opposite direction from a big baddie will result in finding the teleporter, but also in avoiding treasure.

So at this point, without any further improvements, this is what the maps looked like in the editor (circa July 2013). You can see the first one includes some fancier decorations like crumbly tiles and those half-tile transitions mentioned above, while the bottom two are a bit earlier:

pocgentriptych

Locked Doors

To add a bit of variety and reason to explore the corners, we added locked doors, with keycards scattered somewhere else in the level. Rather than block the player’s progress (or frustrate them if they’re in a hurry, with the Blight on their tail!), we decided to use the locked doors only for optional bonus treasures (and monsters!). So, we wanted to make sure the locked doors never appear on the critical path. Since we know which rooms are on the critical path and not, it was an easy enough upgrade to remove one corridor from an off-path room temporarily and replace it with:

(You can also see a locked door in the first panel of the triptych above, if you squint hard)

desert

We still have a couple of algorithm improvements left to implement with this, to make it feel right. We want to make sure, for example, that the locked room has a high chance of extra treasure, and that the keycard spawns in a room other than the one with the door in it.

Alternate paths

And yet almost as soon as we had the critical path and side-rooms laid out, even with locked doors, we realised the levels were pretty boring. They had a lot of dead-ends, which resulted in lots of back-tracking, especially for treasure-hunters… far from the Zen flow of a good level. In fact, a room could only have a maximum number of 2 exits, in the above maps! Not a whole lot of choice going on there.

So, to add variety and ‘flow’, we tacked on room connections, after the critical path and side-rooms have been positioned. Remember how in the “Room Structure” section above I said we mark out a few “doors” per room? Well, we use those again! We (by which I mean Mike tells the engine to) find a couple of doors near each other, and draw a straight line between them, as best it can, turning at right angles if needed.

junction

This added a much-needed refreshment to the dead-end problem, and makes exploration that much more interesting.
Exceptions

As with any rules, there are always exceptions. Even in game design. Maybe especially in game design.

Although most of our game is proc-gen, we also needed to support a few “hand-crafted” levels, including the space-ship that serves as the player’s hub, as well as potentially other, secret special levels, boss fights, etc. We tried to re-use the same data as much as possible. So, for tiles, I use the same TerrainData cubes as in the examples above — see, here’s a peek at the hub, only in this screenshot I’ve taken a normal tile and replaced one with the old familiar “Gen Dirt” from before.

tilehub

I can also place the usual enemies, items, and obstacle data objects I use to populate themes.

We also need to occasionally make tweaks based on powers we add to the game. When we added the “setting fire” mechanic, for example, we made organic tile types (grass, brush, moss) flammable, so the fire would spread organically. So we now have an environment design rule that unless there’s a very good reason, gameplay environments should have a chance of organic tiles appearing. Of course, the average proportion of organic tiles vs inorganic can vary wildly, to increase/decrease that usefulness and danger accordingly, and challenge the player to change their strategy on the fly… but if fire were only useful in one environment, it would be an ineffective mechanic.

Similar tweaks and exceptions need to be made whenever you add a new tool to the player’s toolbox — teleportation, jumping, camouflage, sneaking, invisibility, etc. Assuming you want the power to be genuinely useful in a flexible, user-directed way, your level design algorithm has to take it into consideration.
Future Changes and Lessons Learned

There’s always more to do! The level design for Shattered Planet is aaalmost done, but we want (as you may have noticed in the Critical Path illustration) alternate teleporters that can let you skip to special/secret level themes, special ways for the player to creatively make their own paths to floating rooms, maybe even a swimming ability.

But if we’ve learned anything from all this experimentation from the last few months, it’s:

* Apply traditional level design principles, with flexibility — they’re still useful!

* Procedural generation takes a crazy amount of testing! Just figuring out how to replicate a bug can take hours of loading and re-loading, to isolate the part of the algorithm that is misbehaving.

* Stay open-minded to possible improvements, after you’ve “finished” implementing your procedural generation. As with every other aspect of design, you’ll probably never be “finished”.(source:gamasutra


上一篇:

下一篇: