BLACKSEA ODYSSEY PROCEDURAL LEVEL GENERATIONBlacksea Odyssey Procedural Level Generation
(Our alpha level generation – CLICK IT to see the GIPH)
Our level generation primarily relies on Unity’s powerful parenting system. We match this system with our own procedural level generation algorithms. Each structure that is created is actually a list of children being parented, set and then rotated onto their respective local positions. Of course we run a number of checks to ensure that all of this happens without any overlapping and with controlled spacing to give the world a more authentic appearance. (Will get to more of that in a minute.)
(Aligning identical pieces)
At their highest level every structure in each respective level has a number of locations designated to that structure that tile seamlessly with ANY any other one of the seamless tile locations in that level. Basically this allows us to mix and match our structures in a massive number of ways which is what gives our game that randomized look and feel.
In the above image we have a B location matched to another B location. Every structure can have a number of locations associated to them. These locations are nothing more than Empty Game Objects used to store Vector3 local positions and Vector3 local rotations for each structure. Every Empty Game Object on a structure has a local rotation and position associated with it. For example imagine A is the top seamless tile location for all structures and B is the bottom seamless tile for all structures. A has a local position of Vector2(0,1) and a local rotation of Vector2(90,0). B has a local position of Vector2(0,-1) and a local rotation of Vector2(-90,0). Now to match the two, i take the piece I want to move. Let’s say it’s B in this example. I parent B to the structure I want to relocate, child B to A’s structure. Set B and it’s structure to A’s position and rotate it 180 degrees so that’s it’s facing the appropriate position! Walahh! Your done. Now that might sound like a lot to swallow in one go but fear not I have more information below. Keep reading.
(Aligning multiple pieces)
Each structure has a number of locations attached to it that can generated more tiles. In the above image we have three positions. Think of them as A Left B Right and C Bottom. Each of these locations have a chance of continuing the size of the structure based on how much we want that structure to grow. In the above example we have a structure with three locations on it that it can grow from. In this example the structure has a very high density and grew in all three locations. Using algorithms you can choose to grow your structures as often or as little as you would like. We use a % chance to grow additional structures at these locations based a levels structure density rating. You can also do things like tell your structures to stop growing after they have built a set number of pieces.
Now to keep things all under control you have to have bounding boxes that keeps all of the structures in the game from directions you would otherwise not want them to. What we do is pretty simple, on all of our structures we have trigger colliders on them. Anytime they touch something we don’t want them to touch while the biome is being generated, ie another structure, the player, or a bounding box we trigger an event that tells the script to pick another location (a, b or c) or another structure to relocate too. After a certain number of attempts the script decides there are no other options available for that structure and stops running.
(Two connection pieces.. .with spacing)
Ok awesome… so can I be a pro Unity dev now? Uhmmm maybe but I have some more tricks to show you first.
In addition to tiles connecting at multiple points, over time we felt that our biomes could end up feeling a bit congested and that some biomes could really benefit from spacing.
In the example above we have an A top position matched up to another A top position. As usual we parent one of the A’s to it’s structure. Then child that A to the other A location. Move the original A (the one parented to the structure) to the other A’s position and rotate it until the two positions line up. Additionally in this example we give the structures a random amount of forward spacing to separate the two of them. This is extremely simply because of the parenting system we already have set in place. A pretty simple, nifty little trick that’s sure to break up your tiles a bit. You can choose to do this as often or as little as you want of course.
(A biome being generated)
Here is a biome being generated. The green dots represent points where we used spacing to break things up, and the red dots represent seamless tile locations.
(Our Level Grid…..)
Okay awesome! I think I got most of it!
But wait there’s more!
So what’s bringing all of this together and keeping our structures from all growing erratically?
To start we generate structures in waves by randomly choosing one of the boxes above. After a structure generates it’s likely to spread out into several other boxes. We run a check to see which boxes are still empty and then we generate another structure in another randomly chosen empty location. We do this until every box in the level has been filled, this way we ensure that the biome feels full. We can of course also choose how large we want our structures to grow by telling each structure how many additional structures it can child to it! Of course using smart algorithms is the best way to approach this idea.
Well anyways thank you for reading, and I hope this was helpful for you! Feel free to drop a comment below or ask us any questions regarding our development process.
(Sneak peak of our destructible sprites)