How I created a procedural city


A foreword

In this article I will describe the steps I used to create a procedural city in the Unity game engine. I hope you find it at least mildly interesting and have included as many images as I thought decent. A demo (which can be played in browser) is available here and the source code is here (beware!)

The Voronoi diagram

As soon as I started to learn about procedural generation, I was drawn to the Voronoi diagram. Work like Watabou's city layouts fascinated me and I was eager to learn how to create natural looking shapes from random numeric inputs.


I would use a Voronoi algorithm to gift me the broad strokes of a city layout. Passing an array of random points to the algorithm returned a natural cellular pattern from which I could start moulding in to a convincing street layout.

In order to better understand a Voronoi diagram, I recommend trying to draw one by hand. I never fully appreciated how genius the Voronoi method is until I attempted to follow this Instructable. Even scanning the article gives a great understanding of the steps involved in creating the diagram.

After the algorithm had worked its magic, I was left with a bunch of points and edges to create meshes with (creating meshes procedurally is a whole other topic and I will leave it to Jayelinda's Web and Cat like Coding to enlighten you more than I ever could). Once I had the meshes, I attached each to a unique object and rendered. This left me with something resembling some sort of geography, or some sort of frog spawn. Either way, progress.

Voronoi Diagram

To create streets between each cell I tried to simply each cell, however when I tried this I found the roads were not of an equal width around the city. The solution was to move the outer points of each polygon towards an averaged centre, this way the edges of all cells would be equidistant to the next. Perhaps you could argue that not all roads are the same width but I found it more pleasing to the eye to have them all equal.

Voronoi diagram with gaps

I was pleased with the results but ultimately I found the cities quite samey, whilst all mathematically unique, they all felt the same. They were a bunch of polygons without any real character. I had not emulated the streets of a bustling ancient city with lanes and alleys, or throughways and avenues. To try to combat this I added some more complexity, if a cell was chosen by the random number gods, and wasn't already too small, it would be split. The splitting process took some time to write as it has to avoid making awkwardly shaped cells that would break the building algorithm. Shapes that had too many acute angles for example. The beauty of the Voronoi diagram is how it manages to create natural shapes (and I even used a few iterations of Lloyd's Relaxation to further this) - I was in danger of destroying this. In the end I was able to make it look something like I had hoped.

Voronoi diagram with gaps and splits

So far so good, but all I have really managed is to make is some sort of crazy paving. I was looking to build a city.

The City

Having defined the plots in the city, it was time to populate them. I had worked previously on procedurally generated skyscrapers , however they were essentially symmetrical beasts and had many problems, such as non-uniform windows and a lack of variety. I would need to rethink my approach.

The foundation for the building was already defined by the outer edges of each cell so I could use these to define the boundary, and to provide height and shape, I would use curves defined by (more) random numbers. In my previous experiments I found using only straight lines to define buildings quickly got repetitive so I would use curves to try and build more memorable, or at least stylised outcomes. However, I quickly found generating every curve with random numbers difficult to control. After some experimenting I found a compromise in making only one of the curves 'interesting'. Looking at the screenshot below, the red curve has been made with more daring variables, whilst the blue curves have safer, tighter limits on their randomness.

No alt text provided for this image

The next step is where I get to introduce my debug cube to you, in the image below it is showing us the points on the curve where each floor will start (roughly).

To get a specific point at a specific height along a curve, you need to evaluate the curve in steps and check whether the y-coordinate is equal to or greater than what you need. The accuracy of the height returned is defined by the length of the step. Because I wanted to generate these buildings in real time on a single thread (Unity limitation), I chose to use quite a large step and just clamped the height back to what I was polling for.

Ultimately, it wouldn't be the end of the world if the building shape didn't match exactly to the curve.

No alt text provided for this image

We can see how the curves define the shape and the cubes define the height of each storey.

No alt text provided for this image

An example without cubes showing a risky red curve.

No alt text provided for this image

Finer Details

After another set of curves are used to create smooth corners we get to the issue of windows. What would a building be without windows? To be able to create uniform windows I would need straight lines to interpolate, I could not rely on the curve to give me accurate positions at the speed I needed to render. To generate a full storey 'ring' I alternated between curves for the corners and straight lines for the sides. In this wireframe you can see the straight lines in white and the curved corners in cyan.

Wireframe diagram of curves and straight lines

The next image shows the storey once we add the heights for the windows and apply the meshes/sub meshes and materials. The wireframe give you an insight on how the meshes are constructed solely with triangles.

No alt text provided for this image

Concerning Colour

Colour wasn't something I had consider until almost the end of the project, but after seeing a bunch of drab looking buildings it was obvious I would need to create a system to make these algorithmic creations more appealing to the eye. I had tried randomly creating colours with horrible results, filling RGB values with random numbers from 0 to 255 does not create particularly pleasing variations. I learned about colour theory, about tints and shades and settled on a system where a colour is chosen randomly and rotated around the colour wheel to create harmonies. From here I created the tints and shades and had a full palette to (randomly!) choose from.

An image of the colour creation method creating random hues with shades and tints displayed inside.

No alt text provided for this image

An example of the storeys of the stepping through tints and shades. You can see the top and the bottom band of the storeys stepping through the palette in different patterns. These patterns are also randomised and I had a lot of fun creating lots of different ways for the palette to be displayed.

No alt text provided for this image

But I wanted to go further. As it stood, each building was an island, there was no overarching feeling or style to the city as a whole. I thought it would be a good idea to create relationships between the adjacent cells. I had already worked out which cells were adjacent to each other when I was splitting the cells so all I had to do was step through each cell, and give its adjacents a harmony (high chance) or contrasting (low chance) colour from the colour wheel. The colours sweep and change naturally from cell to cell and only now and again appear jarring if the random number generator deemed it so.

No alt text provided for this image
No alt text provided for this image
No alt text provided for this image

It's over

This brings us to the end of the post, I'd like to thank you for making it to the bottom! Have a lovely day :)

Get Delly Welly's Building Generator

Comments

Log in with itch.io to leave a comment.

Great writeup and fun read. I use Voronoi  for generation in  several places in my game, like biome assignment and foliage/ground clutter placement.

I love your application of color harmonies... I'm interested in what other ways you will push the tech you're developing, keep it up!

Thanks for spending the time writing this up :)

Hey sorry, just noticed the reply. I have a decent start on creating interiors for this but haven't worked on it in a while. Hopefully after I finish my current side project I will have more time for procgen, I miss it! 
And yes, Voronoi is awesome, but sometimes tough to get it to do what you want. Regarding colour harmonies, I was pleased with how quickly I could pull that system together, the cities wouldn't be anywhere near as nice to look at without it. 
Thanks for the comment