# Unity - Tile based river generation

I have made a map generation in my tile based game. It almost exactly does what I want, except for 1 thing. The rivers look like this:

The problem with this is, the water is not realistic. It are just some spots random over the world. I want to make a realistic river generation. Which would include different sizes (between 5 and 20 block wide), branches, lakes and different depths (by changing the colour of the water). What is the best way to do that?

Here is an Simcity 4 example of what I mean with realistic rivers:

My code:

waterOffsetX = Random.Range (10f, 300000f);
waterOffsetX = Mathf.Round (waterOffsetX) + 0.5f;
waterOffsetY = Random.Range (10f, 300000f);
waterOffsetY = Mathf.Round (waterOffsetY) + 0.5f;

for (float x = -gridX; x < gridX; x += 1)
{
for (float y = -gridY; y < gridY; y += 1)
{
Vector3 spawnPos = new Vector3 (x, y, 0);
float perlinWater = Mathf.PerlinNoise (x * seedWaterX + waterOffsetX , y * seedWaterY + waterOffsetY);

if (perlinWater > perlinThresholdWater) {
GameObject waterTile = Instantiate (water, spawnPos, Quaternion.identity) as GameObject;
}
}
}

Values:
seedWater (X & Y) = 0.1
Grid (X & Y) = 50
perlinThresholdWater = 0.6

• you can use GetPixel from map's picture so Implement it on tile map Commented Jul 31, 2016 at 14:15
• Yeah but in this case I wanted to show what the rivers looked like and why I don't like it this way. For that purpose I didn't use GetPixel Commented Jul 31, 2016 at 14:34
• Is your map perfectly flat, or is there some sort of upward slope at different points? Commented Mar 15, 2017 at 18:59
• It is perfectly flat. There might be some hills, but that would be just a change of texture Commented Mar 15, 2017 at 19:52

I wouldn't use straight perlin noise for this. The closest I would get would be to use something like Perlin Worms to generate the data for plotting the rivers.

However, I'd take a procedural generation approach. My answer here is where I'd start. You'll build the river backwards. Pick an end point for your river at some point along the edge of your map. Choose an end width, like your 20 tiles for a wide river. From there, you'll step away from that edge of the map, plotting the course of the river. Each step, there's a chance of:

1. Change direction. Weighted chance. Higher weight to continue straight, then to turn left or right, with a preference towards the opposite direction of the end.

2. Branch. The river splits its current path into two, dividing its current width between the two paths. Each new path takes its own steps.

3. Reduce in width. This accounts for water that's being added to the river that's too small for a tile.

Each of these options can happen more or less frequently depending on the width of the river. For example, you may want to change direction much less often when the river is wide, and more frequent direction changes when it's narrow.

Path
{
width
startingPoint

pointWidths
lastPointWidth
currentDirection

Step()
{
stepChoice = GetStepChoice(width) //weighted chance to decide what to do
switch(stepChoice)
changeDirection: //change the current direction
currentDirection = GetNewDirection(currentDirection)
reduceWidth:
width--
branch:
newWidth = divideWidth(width)
width = width - newWidth
noChange:
//Do nothing, just step forward below

lastPointWidth = (lastPoint+currentDirection, width)
}
}

RiverMaker
{
Path[] paths
Path[] donePaths
Start()
{
MakeRiver()
}

MakeRiver()
{
//process each path until there are none
while(paths.count > 0)
{
for each path in paths
{
if(path.isNotEnded)
path.Step()
else
paths.remove(path)
}
}
for each path in donePaths
{
//Step through each path, using the width and position
ApplyPathToWorld(path)
}
}
}

• That seems to be the answer, but could you add some code in for me on how to use this within my code? Commented Jul 31, 2016 at 16:55
• The code for this type of algorithm is pretty in-depth. I added some pseudo code for you to implement. There are many more details you'll have to figure out. If you need code specific to your project, you can contract me at, say \$80 an hour? Commented Jul 31, 2016 at 17:35
• Well, I don't want to invest too much in this game, money wise, so that is a no for me ;) I won't set this as the answer just yet, I'll wait and see if someone else comes with a answer Commented Jul 31, 2016 at 17:37

There is a well-know article on how to generate terrain from 2010, here:

http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/

with an update, here:

https://www.redblobgames.com/maps/mapgen2/

Now, for beginners, you achieve natural rivers without using Voronoi diagrams, if you generate a height map and then plot the river from the river source to the sea or ocean (basically the lowest point on your height map, which is the river end, so to speak), like so:

• a) start location, direction and height
• b) if same direction as last iteration: random direction, but only within 180° angle (to prevent turning back)
• c) find the lower level (height) and move there, if possible
• d) every few steps increase river width (so it gets wider to the sea)
• e) if you hit the water level: done
• f) if you do not hit water level: repeat b), c), d) and e)

Lakes and ponds are different and done in a second step. It means, when you look closer, you see that the SimCity rivers work without lakes, which means that lakes were either added before or after the river creation.

There's more to it, of course. For instance, if you change the direction every turn, well, your river feels weird, so you should change the direction only after a random number of steps. But I hope it helps.

I always work with the combination of height, rainfall and temperature (and wind too, actually). This way, the rainfall map shows where lakes will be. And, lakes and random "river sources" are then where I start rivers. What is great about rivers is that they make your landscape feel less flat, as if there is some hidden height, even if everything is flat.

If you lack a height map, because you are in flat lands, well, just create a fake one and see how the rivers behave. I am sure that SimCity generates additional height maps in order to make rivers more natural.