Terrain Generation for Procedural World

Okay, so I’ve already posted this once but Google Chrome crashed so I apologize if anything I type this time around seems a little abrasive.

I’ve been playing around with Unity, both with the Unity Editor and MonoDevlop for Scripting, and am testing out a proof-of-concept design for a Civilzation-style game.

Using a Mersenne Twister random number generator (RNG), I am programatically generated a mesh of interactable width and height, as well as allowing the size of the tiles to be changed too. I have also implemented a basic mouse-over system which tells the player what tile they are currently mousing over.

The issue that I now face is trying to make the world more organised. For the moment, as I said before, I am using a RNG which randomly choosing a tile from a predetermined list. The predetermined list is now problem; the problem is trying to group similar tiles together; i.e. having vast oceans with land masses scattered throughout the world.

I have a basic concept with regards to the generation process, but I am not entirely sure as to how I can achieve this inside of the game engine itself.

  1. The first step in my world generation would be to iterate through all the tiles in the world and make them all deep ocean tiles. In essence, this means that we are starting with an empty world, simply populated with water. This would form the ‘base layer’.

  2. Next, the world would be iterated through again and placeholder land masses (i.e. grouped tiles of land that are large enough to be inhabited). They wouldn’t be the actual land tiles yet, just enough for the ‘base layer’ to see where the land is situated.

  3. Deep ocean tiles that are situated within a certain number of tiles (probably a random number so that the coastlines are uniformly bordered by shallow water) are converted into shallow ocean tiles, to allow players to board boats and traverse near to the land.

  4. The previously generated land tiles are now iterated through and, dependent on a variety of factors, are converted into their appropriate tiles (sand, grass, mountain, etc.).

  5. One final iteration of the world would clear out any silly generation (for example, an island of size 1x1 generates and is then determined to be a mountain, wherein the tile - i.e. the whole island - cannot be populated) by returning them to either flat land or water.

So, that’s the sort of proof-on-concept behind the terrain generation but I have had no luck finding any tips or tricks or suggestions on how to achieve this.

Does anybody know? I would be incredibly appreciative if somebody did.

Thanks again to anybody who can solve, help solve or point me in the direction of a post that can solve/help solve my problem.

Thanks.

Classic case of why semantics is important.

No game with a terrain generation algorithm uses random generation, it’s all procedural. A simple way to go about this is to think in “passes”.

First pass:

What size are the landmasses? Whatever we want, first step is to fill the map with water.

Okay, there’s water. Let there be land. Let’s make 2 spots at roughly equal distance from the center of the map, slightly randomized. Now let’s begin filling a circle, until the landmasses touch. Retract a couple of sizes, then cleave a good 10-30% of the circles’ facing sides off, so we’re left with rounded rectangles, pretty much.

Second pass:

How cold is the planet? Let’s make icecaps this far with randomized edges jagging outward.

Okay. How about dotting some islands here and there, around the continents. Sizes 1-5 tiles, we don’t want big and fancy. Is there space for another big island that doesn’t quite qualify as a continent? Maybe we should slap one in if the RNG favors us. No? That’s okay too. Maybe a smaller one then, in a different location? Oh, okay, great. Let’s make it a small circle, and then chop off some of the edges, rough it out.

Third pass(es):

How about we raise and lower the terrain? There’s many ways to do this reasonably and simulationwise, but let’s do it random for now.

Third B pass:

Having a mountain nearby should also mean higher appearance of hills, so let’s take that into account after making mountains.

Third C pass:

Now that we have mountains and hills, let’s do the opposite! Rivers and stuff, heading outward from mountains in a feasible direction avoiding hills using simple pathfinding algorithm until they hit the ocean. Easy peasy.

“Fourth” pass:

Now we start hammering shapes in rougher from our base shapes. Let’s call it “erosion simulation”. Basically cutting chunks off the terrain’s edges, as well as forming them in a sort of a random coin-flip fashion. Let’s do this a few times over. We can also check for thinness and width of the terrain here to prevent long strings of land (think south america) from being chopped into the philippines by a factor of how many mountains and hills they have for instance.

Fifth pass:

After that debacle, dot some lakes in, and then form more rivers out of some, or all of them, up to you! Make sure lakes are not formed next to, or too close to oceans. Let’s give an arbitrary 2 tiles in-between.

Sixth pass:

Now that our terrain is pretty much shaped, we pass from north to south, or south to north, whichever you fancy, and apply the appropriate terrain tiling based on elevation, rainfall, distance from equator and other factors. Or could just form big invisible circles like we did with actual terrain generation and only apply the terrain changes to non-water areas. We then rough up the circles as before.

Seventh pass:

Form appropriate coastlines. Simple as that. Overwrite non-hill non-mountain (possibly non-tundra, non-jungle too) terrain on ocean coasts.

These can go in either order, but form actual coastal waters (more shallow) around the coasts x tiles away with very small chance of stretching 1 tile further (which in turn gives increased chance for the neighboring tile to do so aswell).

Eigth pass:

Dot the appropriate terrain with the appropriate resourcs. Calculate the size of the terrains doing this so you don’t place too many.

Ninth pass:

Assign feasible player start positions based on terrain and resources.


Aaand you’re done.
I’ve some experience in tinkering with Civ 4’s map generation, and this is a roughly idealized version of how it’s actually done. No actual code, because me writing your script won’t teach you anything.

As for how to do this technically, you first need a tile based system, and the appropriate tiles. Do not even imagine using Unity’s Terrain to do this.

When you have a system that can be told, by code, to place a tile of your choice in location of X and Y (with possibility of actual 3rd dimension if you want to be fancy), and can tell you what tile is in X16Y58, you’re all set. It really isn’t very hard, considering Unity comes with a set of coordinates to begin with. All you need to do is make sure the tiles can match eachother (or can be deformed to do so).