Procedural World Generation


The foundation of any open-world survival RPG lies in its world generation. For the 2D RPG Project Accelerator, I’ve built a procedural terrain system that creates natural-looking islands using noise functions, terrain templates, and smart resource placement.
Let’s break it down.
🌍 Island-Based Procedural Generation
The world map is generated on a grid using Perlin Noise to determine elevation. Each tile’s height decides what kind of terrain it becomes.
But to make sure the map actually looks like an island (and not a weird square blob), I applied a falloff function to lower elevation near the edges.
🔁 Island Falloff Function
The falloff function is essentially a radial gradient from the center of the map:
float distanceX = Mathf.Abs(x - mapCenterX) / mapHalfWidth;
float distanceY = Mathf.Abs(y - mapCenterY) / mapHalfHeight;
float distance = Mathf.Max(distanceX, distanceY);
float falloff = Mathf.Pow(distance, falloffStrength);
heightValue -= falloff;
This ensures the center stays high enough for land while the edges naturally fade into water — perfect for island generation.
🌳 Terrain Templates
Each tile gets a terrain type based on its final height:
if (height < 0.3f) return TileType.Water;
if (height < 0.4f) return TileType.Sand;
if (height < 0.7f) return TileType.Grass;
return TileType.Rock;
These thresholds are defined in terrain templates, which makes the system super customizable.
Each template includes:
Height thresholds
Tile sprites and colors
Spawn rules for resources and props
You can easily create new biome types (snowy, volcanic, desert) just by tweaking or swapping templates.
🌾 Resource Distribution with Poisson Sampling
Resources like trees, ores, and berry bushes shouldn’t be placed randomly or uniformly. That’s where Poisson Disc Sampling comes in — it ensures evenly spaced, natural-looking placement.
📐 What is Poisson Sampling?
It’s an algorithm that places points with a minimum distance between them. Perfect for spreading objects in a way that feels organic.
✅ Example Usage
List<Vector2> treeSpots = PoissonSampler.Generate(
regionSize: new Vector2(chunkWidth, chunkHeight),
radius: 4f,
sampleAttempts: 30
);
Once you have the points, just check the terrain type under each point, and if it’s valid (e.g., grass), place the resource.
foreach (var pos in treeSpots)
{
if (GetTileAt(pos) == TileType.Grass)
{
Place(TreePrefab, pos);
}
}
This method gives forests, berry clusters, and ore veins a believable, spaced-out look.
📃 Procedurally Generated Tilemap with Resources
🚀 Why This Matters
The combination of island shaping, terrain templates, and resource placement ensures every new world feels handcrafted — without any manual work. It’s procedural generation with just the right amount of control.
📆 What’s Next?
With this system in place, upcoming features will focus on:
Saving/loading generated maps
Dungeon entrances and POI markers
📃 Try It Now
This procedural generation system is available as part of version 1.2.0 of the 2D RPG Project Accelerator.
https://assetstore.unity.com/packages/2d/2d-rpg-project-accelerator-296300
As always, hit me up with ideas, bugs, or questions. Can’t wait to see what kind of worlds you build! 🌍
Subscribe to my newsletter
Read articles from Deniz Traka directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
