5 tips for using procedurally-generated content in your game
Isn't procedurally-generated content brilliant? Playing the same game over and over again, yet receiving what can be a satisfyingly different experience each time -- and from a development perspective, the prospect of building only a small amount of content, and then being afforded the opportunity to focus more on making your title as enjoyable as possible.
OK, so procedural generation doesn't always work so swimmingly, and there are plenty of mediocre games that have tried and failed to incorporate randomly-placed content. But taking the "less is more" approach, as Eufloria dev Rudolf Kremers recently called it, is a great way for indie studios to free up time to focus on other areas of development -- if done successfully.
Cargo Commander from indie studio Serious Brew manages to ride procedurally-generated content into the sunset, with players zipping through random space containers to grab treasures as quickly as possible. A sort of Spelunky in space, if you will.
"I've always been interested in procedural content creation, from the BASIC programs I wrote when I was little, through fractals and my training in artificial intelligence, to the many hours I spent in games that had any form of procedural generation," says Maarten Brouwer, co-founder of the studio.
Through the creation of Cargo Commander, Brouwer has learnt a great deal about what to aim for -- and what to avoid -- when it comes to level generation. "It didn't always work out as well as I would have liked," he admits, "but had several cool and surprising results that really improved the game."
Here, Brouwer offers his top five tips for other studios considering procedurally-generated content in their games.
1. Pick your battles
"Don't expect to simply pick a section of the game design and make it procedurally-generated. Adapt the game mechanics, theme and the procedural generation to each other to make it work as effectively as possible, and try to focus on high bang for low buck.
In Cargo Commander, we made the uniquely generated levels fit well with the lonely space exploration theme: this time you really go where no man has gone before! At the same time, the theme is not too serious, so that generated levels that are a bit odd don't seem out of place. Also, the generation really impacts the gameplay and is not just a backdrop. The selection of objects (enemies, explosives, burners, items) and features (gravity, layout) differs for each container, creating ingredients that the player can combine in various cool improvised ways.
In other areas, I tried to steer away from features of procedural generation that wouldn't be effective. For instance, a notoriously hard thing with level generation is to ensure that levels can be solved - 'can that ledge with the key be reached, using the items that are available?'. Though there are a few checks to minimize impossible situations, the level destructibility and space navigation make sure that the player almost always can create a route somewhere, and because containers can be skipped, it's not a big problem if one cargo item is unreachable. For the sector pass containers, that are more like a puzzle and do need to be solvable, I kept the randomization to features that wouldn't influence this, and relied on handmade levels for the rest."
2. Remember that randomness is random
"The levels of Cargo Commander are randomly generated. The sector name (that players can pick from a list or type freely) determines the random seed, and all levels in that sector are generated from random values based on that seed. However, it's important to take the attributes of randomness into account when deciding how to use the random values for generation.
The usual way to look at randomness is by using statistics. For instance 'the container size picks a value between 3 and 9, so on average containers have a size of 6', or 'each container has a 25 percent chance to spawn a medkit, so on average they're encountered once each 4 container'. However, unless the population that they say something about is large enough, in reality such numbers are less useful than they seem. Just like rolling 1s in a row may cause a barbarian to be defeated by an angry hobbit cook despite the barbarian's level 10 and Loincloth of Awesomeness, the player may encounter only really tiny containers in a sector, with an average far below 6.
In many cases this is not a problem and may cause nice variation, but when game balance is involved, this can become a problem. If despite the 25 percent, the first 20 generated containers don't have medkits at all, the game gets harder or more unfair than intended. In that case it may be better to use the randomness in a way that can't affect game balance too much, like randomly dividing 5 medkits over the 20 containers, or randomly vary the number of containers between the first medkit and the next."
3. Try anything to add 'life'
"In my opinion, the hardest part of procedural generation is to avoid getting randomly thrown together objects that feel lifeless. When a level designer crafts levels, (s)he adds personality to it with unique features or things with an extra meaning above the mere components. I've tried several things to improve this:
Use introspection. If you quickly draw a map on paper, why do you choose the features that you choose? Even simple things help here; I noticed that I often use symmetry, or base designs on general patterns, and incorporating that in the generation code helped a lot.
Procedurally-generated containers from the GALLIFREY sector
Cheat by secretly mixing in handmade level design. I've created a number of tiny pieces of level that get mixed in the rest of the generation process. By only using their functional parts and have the other parts and the appearance be randomized, players won't recognize these reused parts too quickly. It’s almost depressing to see how well these tiny hand-designed pieces work.
Create specialness. If half of the assets are used in everyday levels, but the other half are encountered rarely, each encounter of a rare asset automatically makes the level more special. This also works for parameters; if container size is normally between 3 and 9, a rare encounter of a container of size 15 becomes a memorable event (even/especially when the resulting parameter is outside the bounds for optimal gameplay).
Let assets radiate life. Daniel Ernst, the other half of the dev team, made detailed models that add a lot of character, so that even a simple level has atmosphere. If they hint to something more, a story behind the story, then a random combination of assets can suddenly get an extra meaning."
4. Prepare for tough testing
"When I built the generation system after some first prototypes, I created a rather complex layered system, with the sector randomizing boundaries in which the rest of the generation worked, further influenced by such properties as the selected container theme, the container size and the wave number.
I had no idea if it would work and be balanced, and then I encountered a problem: I couldn't test that either. When I'd try out a sector and encountered five containers that are full with enemies, did that mean that too many enemies get spawned? Or was this sector one of which the enemy count was randomly set very high, combined with the specific container sizes? Or did a few random rolls just came up with a lot of sixes?
For most parameters I tested the average value and a theoretical min and max, but because many parameters influence each other, this was not definitive.
After playing many games, some balance problems can become apparent, but it's easy to conclude some issue based on one playthrough, while a next playthrough shows nothing of the sort at all. Knowing what effect a property adjustment has is even harder. In the end setting/tweaking the properties was mostly done on gut feeling. Having a beta with a lot of people was essential as well.
A sector pass container plan
This is also the cool thing with procedural generation, of course: if it's complex enough, even the designer has no idea what might be produced!"
5. Do something with it!
"The use of procedural generation opens up all kinds of possibilities that aren't possible with static level design, much more than merely adding an infinite amount of levels (which quickly gets boring anyway). In Cargo Commander, the simple mechanic of entering a sector name that seeds the generation, with each name having its own online leaderboard, worked surprisingly well.
More interesting possibilities include creating levels based on the status of the player, or what the player has done in previous levels; the whole world can change based on his decisions! Or the player can be given explicit influence, by choosing certain parameters, or perhaps have him make a basic level outline that's further filled in automatically.
Mixed with other game elements, even more exotic options are possible. To me, procedural content generation, artificial intelligence and user generated content are mechanisms that can elevate a game from a static experience to a highly organic, living whole."