This is an old article that was written as a dev blog post for Epistory, a typing adventure game and the first project I worked on at Fishing Cactus.
As in most puzzle / adventure games, Epistory’s level design, is designed manually from the world layout to the smallest puzzle. But to save time and money, we need to automate everything else, like generic and repetitive patterns or effects that give life to the world. That is what this article is about: the level building of all the things that are not unique or designed for a specific purpose.
A good example of that is the placement of every tree in a vast forest. We know what we want (a group of trees), where (a delimited zone), and how (dense and diversified). So we have parameters that could drive a procedural generation of trees. By the way, game engines have similar tools for vegetation generation.
But in the same time, we want to draw a path in that forest with a specific level design, and the trees’ shape and placement influence that design. This is where lies the dilemma: a full control allows us to place each tree as we want but takes a lot of time, and a full procedural gives results that will never be perfect.
If you want a metaphor – everyone loves metaphors – imagine you are drawing a diagram or taking notes. If you use one black pen, the result is not as clear as if you use a color code. But if you have full rainbow pens at your disposal, you are always tempted to choose the right color for the right thing and, inevitably, you lose time. Limitations can have a positive effect, be it saving time & money or coming up with creative solutions.
Before explaining our solutions to that problem, I need to talk about the tools we are using and a bit of our level building workflow. Epistory’s level design is tile based and we use the Tiled editor, which is perfect to prototype, create and edit tilemaps really quickly.
The essential criteria when choosing a tool are its usability and the level of control it allows (or in reverse, its constraints). Of course there is also the cost to buy or develop that tool, but I will not talk about that aspect here as I am focused on design (plus Tiled is free and Unity plugins are relatively cheap).
You can get used to Tiled pretty fast and come up quickly with a rough prototype. It saves you time while doing repetitive tasks and is easy to edit. In short – as long as you stick with tiles – its has no big usability flaw.
So I start by creating the map with Tiled. But the game is in 3D and developed on Unity. So here comes the Tiled to Unity plugin that uses the exported tilemap to generate the level in the Unity editor. It simply places the right 3D asset at the right place.
For more specific features, we modified the plugin source code to add more functionalities. An example: when you progress in the game, new zones of the world will appear. So we need to be able to delimit those areas. The easiest way to do it – from a level designer point of view – was in a specific layer on Tiled. So the plugin can also add the generated tiles to a tile manager, and determine to which zone it belongs from that “Zones” layer.
Finally, I place interactive elements and puzzles manually in Unity. It is easier and more editable this way because they all have specific behaviors and parameters. Unique decor used as landmarks and localized visual effects are placed the same way at the end.
In my opinion, the best solution to the “control vs automatism” problem is the more obvious one: a random (or procedural) generation in the editor, which is corrected manually only where it is needed. Note that the random aspect only exists in the editor, it cannot be regenerated in game. As long as you do not change everything, that controlled randomness has a good time / quality ratio.
For a concrete example in Epistory, I will use the example of the forest again. I use the random mode on Tiled to randomly paint with elements from a selection. Then I change some of them manually in Unity if it creates strange-looking patterns. I try to have a continuous border for smooth collisions. And I place a few mushrooms, again with a bit of randomness.
Another solution is to use a more ordinary procedural generation but limited to a very few parameters and/or a small area. Here the randomness happens in game, but not on the key elements of the design. That localized solution allows a correct placement at macro scale without having to place small elements one by one.
In Epistory, we use that method to spawn critters. Potential spawn points are defined and only some of them are chosen a game start. They are not always at the same place but always at a suitable one.
There also are large zones in which groups of particles are randomly spawned. That lets us quickly define the areas in which you will find butterflies, fireflies, fog and so on.
Finally, only one attribute of an element can vary randomly. This way, you can use item variations that keep – for example – the same size and function in game but can look a bit different. You do not have to bother about the small variations if they do not affect the design.
On Epistory, we made little use of that but we consider adding variations like size and texture for trees and rocks, rotation on tiling textures, ripped paper effects on some tiles, and so on.
I am sure there are plenty of other solutions and applications to them. I hope that you found those ones interesting and that they could be useful elsewhere.