We’re making our open-world game Sir, You Are Being Hunted using some procedural techniques. The most important of these generates the environment from raw scenery materials. This post details a little about how that process works.
The British Countryside Generator, as we’re calling it, is our procedural world engine for Sir You are Being Hunted. It’s plugged into Unity, which we are using as our overall development toolbox. It’s still a work in progress, but already delivers much of what we want for our game world, without us having to hand-place environmental features, as you might in traditional level editing. You can see some examples of the environments produced by our system here and here. (Continued below)
There are a few main reasons that we chose to use procedural generation over less code-based approaches. The most important one, of course, is that as a small independent developer we could never afford the resources, production time, or team size to produce the large, explorable game worlds that we all love at Big Robot. Procedural content generation allows us to use sneaky maths and coding to overcome many of those issues and stay closer to the open world style vision that we are aiming for. Another reason for using procedural techniques is that it gives us the ability to generate a huge number of environments that will be unique to each player and really increase the levels of replayability and emergence in the game.
In short: maths lets us do what our budget does not.
overhead scene view of a small island, showing cell arrangement
I’ve worked on a number of procedural world generation tools before, but this particular engine is unique in that the intention was to generate a vision of “British countryside”, or an approximation thereof. To approach this we identified a number of features in the countryside that typify the aesthetic we wanted, and seem to be quintessential in British rural environments. Possibly the most important element is the ‘patchwork quilt’ arrangement of agricultural land, where polygonal fields are divided by drystone walls and hedgerows. These form recognisable patterns that gently rise and fall across the rolling open countryside, enclosing crops, meadows, livestock and woodlands. This patchwork of different environmental textures is something that is very stereotypically part of the British landscape. I looked for a mathematical equivalent we could use to simulate this effect and quite quickly decided upon using Voronoi diagrams.
Voronoi diagrams are a common feature of procedural content and spatial division maths. They work by taking a number of points in space and then identifying the boundary lines that lie between those points. The result is a little bit like when a load of bubbles expand together and force the walls between them to meet at a specific intervals, you end up with a kind of cellular division of space which looks remarkably like their quilts of the British countryside. Another advantage of using this form of spatial division is that it becomes easy to dictate different cell/regions as natural biomes within the world, where each cell can be defined as belonging to a particular type of countryside (forest, fields, lakes, shorelines etc). I could then scatter points across the world in a controllable distribution to generate a ratio of different biome types (10% forest, 30%, hills etc), each point dictating the enclosing voronoi cell.
Strict grid and disturbed grid voronoi cell layouts
I generally use what I’d call a disturbed grid distribution, which means that instead instead of just selecting random points (which can give you a very chaotic and squashed type of structure) the code places uniformly distributed points on a grid but allows a small random amount of movement from each grid location. This allows the creation of interesting organic divisions without worrying too much about compression or expansion in different parts of the of the grid. Once the diagram is constructed and I have an overhead topology of the world the next step is to use that graph to create a heightmap.
The way I do this is to initially to take the corner points of every voronoi cell and assign a value to them from a multi-octave perlin noise function (the centre point being an average of the corners), this essentially treats each region as a polygon and results in a very chunky-looking terrain. The next step is to apply another layer of much more fine-grained perlin noise, this adds incidental detail and a more organic feel to the overall slopes of terrain. I can also use the region types to customise this proccess, allowing hillside regions to increase the degree of deviation and shorelines to flatten the heightmap slightly. On top of this process I use a number of algorithms to generate coasts with cliffs and sloping shallow beaches (by forcing altitudes up or down within a sinusoidal shape or island mask).
Rocky hillside regions
Once this is done the engine then uses the height information to produce a terrain splatmap where different textures are assigned to areas according to altitude,slope and region type. This results in sandy beaches, rocky highlands and meadows inbetween. There are also a number of ‘noisy’ functions that make the textures intersect more organically by adding goat type trails, blurring and dithering. There are also additional alterations made to this splatmap later as the engine deploys the actual models too – walls, buildings and so on.
Next the engine starts to populate the individual regions with these models. The way system works is that you can have as many region types as you like, but each region is responsible for placing its own content. This doesnt stop regions sharing functions and characteristics though, for instance walled fields, hedged fields and fenced fields all share the same code for ‘wall’ building. In these cases a function’drops’ wall segments along the perimeter of the cell, leaving gaps for gates and paths. The individual pieces are selected randomly from a set and angled according to the wall direction, as well as some slight variational noise. The resulting modelset is then combined into a single mesh for rendering speed.
Copses and forest regions are similar types of the wooded area which differ only in how the trees are distributed and what pool of models they use. Copses use a radial formation and forests use a disturbed grid. In each case the individual models are scaled, rotated and positioned in different ways to create variation.
Scene view of a small village layout
One of the more complex regions are the village cells. These have detailed scripts to generate the layout of houses, roads and gardens. First, roads are drawn into the terrain splatmap extending out at different angles from the village centre. Then a series of functions line the roads with houses and other buildings. Finally there is a chance for houses to have a range of garden types behind them, these gardens are themselves populated by various scenery elements and other features. Villages provide a much more complex environment for exploration and combat, and may include lootable containers with valuable resources. They are also more likely to harbour enemies.
Player view from the ruined back yards of a village region
There are around a dozen region types at the moment but the system is built to be extendable and we plan to include many more regions such as, marshlands, graveyards, bouldered areas, coves, ravines etc. Each region has a rarity value attached to it which dictates how likely that region is to appear in any generated world. By altering these values you can vary the overall region distribution of any generated island, this allows the system to produce an environment that is say heavily forested, full of rocky hillsides, or built up and well farmed etc. The generation system ties directly into the Unity terrain features which allows us to benefit from the built-in level of detail optimisation and terrain foliage features. The other region produced content is culled by the region code itself.
The system far from not perfect, and we are constantly tweaking parameters and rewriting code to improve the stability and range of worlds produced. However, one of the most exciting parts of procedural content generation is the fact that it can produce unexpected results, players can stumble across regions that due to a particular combination of features appear really unusual. In testing I’ve found villages collapsing over cliff edges, trees submerged in lakes and roads from nowhere to nowhere. There is actually something nice about finding these anomalies because it really feels like a unique discovery, proving that you are wandering your own, individual version of the game world.
A case where the code went very wrong! floating hedgerows!
Although the technology could be expanded to produce a near infinite gameworld we felt that it was sensible to present the environment as a series of islands – perhaps the remnants of a flooded future Britain – each generated individually but with their own range of biomes and topography. This allows us to dictate a sense of progression too, and avoid the ‘same same but different’ feeling that some procedural worlds produce. The idea of a procedural archipelago fits well with our tweedpunk world style and the surreal nature of your robot gentlemen foes is reflected in the dreamlike nature of the landscapes produced.