Rochipelago: A fully customizable NON-VOXEL procedural blocky island generator

Every island you see below is built out of Parts at runtime. No Roblox Terrain, no meshes, no imported assets. Press Play and you get a fresh island: beaches, terraced hills, mountains, trees, rocks and grass, all generated from scratch.

The place is uncopylocked. Wait a few seconds for the terrain to finish generating upon joining the game.
(ISLAND TERRAIN GENERATOR | Play on Roblox)



The default island: sandy beach ring, forested interior, terraced hillsides.


Customizable biomes: 4 built-in examples


What it does

  • Procedural terrain. fBm noise with domain warping, plus explicitly placed mountain peaks so every island gets a readable silhouette instead of a lumpy blanket.
  • Minecraft-style beaches. Coastal tiles are classified per tile: low and gentle ones become flat sand, tall or steep ones become stone shore.
  • Terraced hillsides. Height steps between tiles get filled with “bands”, so hills read as terraced ledges rather than sheer walls.
  • Crumbly dirt. Exposed dirt faces get chunky cubes bolted onto them via BSP slicing, so dirt looks eroded instead of like a clean box.
  • Mottled ground. Thin lighter overlays scattered on grass and sand. Cheapest trick in the kit, does the most work.
  • Trees, rocks and grass. Rocks rejection-sample their spots so they don’t intersect trunks. Grass is client-side only (see below).
  • Multiple islands. Island.generateAt(position, overrides) builds an island anywhere, with its own biome, size and settings. Archipelagos in a few lines.

Everything is customizable

There’s one file, IslandKit.Config, and it’s the only file most people will ever touch. It’s plain values with comments on every one:

Config.seed = 12345                 -- same island every run
Config.island.radius = 600          -- bigger island
Config.peaks.height = {80, 160}     -- real mountains
Config.biome = "Snowy"              -- reskin the whole world
Config.foliage.drawDistance = 70    -- the big perf lever
Config.dirtify.enabled = false      -- cheaper, cleaner terrain

Grass colors, dirt colors, beach width, sand shade, patch density, tree and rock density, grid size, noise, the sea. It’s all in there.

Biomes are pure data. Duplicate Biomes.Forest, change the colors, point Config.biome at it. There’s no code in a biome file, so you can’t break the generator by writing one. Ships with Forest, Desert, Snowy and Volcanic.

Props are drag-and-drop. Drop Models into IslandKit.Props.Trees / .Rocks / .Foliage and they get scattered automatically, no code changes. (One rule: a prop’s pivot must sit at its base.)

Many islands

local Island = require(ReplicatedStorage.IslandKit.Modules.IslandGenerator)

Island.generateAt(Vector3.new(0, 0, 0), {
    island = { radius = 350 },
    spawn  = { placeSpawnLocation = true },      -- players start here
})
Island.generateAt(Vector3.new(1300, 0, 400),  { biome = "Snowy",    island = { radius = 200 } })
Island.generateAt(Vector3.new(-1100, 0, 900), { biome = "Volcanic", island = { radius = 300 } })

Every Config field works per island, so islands in one world can be completely different. They share a single sea that grows to reach the furthest one. Islands can be generated at any time, mid-round, procedurally, or in response to a player, and the foliage system picks up new ones on its own. There’s also getIslands(), clearAll() and wouldOverlap() for placing them procedurally.

A note on performance

Ground cover is normally what causes lag: tens of thousands of grass tufts is not something you can replicate or render. So the grass is never replicated. Each client derives the identical layout independently by seeding an RNG from each grass cap’s world position, then only instantiates the foliage near its own camera, pooling and recycling models as you walk. Everyone sees the same grass, and it costs zero network traffic. Cost scales with draw distance, not island size.

Generation itself is spread across frames, so the server never hitches while building. A default island takes about 8 seconds.

Structure

ReplicatedStorage.IslandKit
├── Config          ← the only file you need to open
├── README          ← full docs
├── Biomes/         Forest, Desert, Snowy, Volcanic
├── Modules/        Noise, HeightField, Tiler, Builder, Dirtify, Patches, Scatter, IslandGenerator
└── Props/          Trees, Rocks, Foliage

Tiler decides, Builder builds. To change the shape of the island you never need to open Builder. To change how it looks you never need to open Tiler.

Full documentation is in the README

IslandKit.README covers all of it: setup, every config option, writing your own biome, adding props, the module architecture, performance levers, runtime regeneration, and how to build mining, painting or placement on top (every terrain part is tagged and named by role).

Take it, tear it apart, use it in whatever you’re making. If you build something with it I’d love to see it!

13 Likes

You might wanna look into improving that foliage implementation. There’s a very noticable framerate drop originating from how it fades in/out distant foliage.

1 Like

Yep, especially with the fades this is what I’ve also noticed. Some things that could help:

  • Use an octree to find foliage closest to the player much more efficiently
  • Don’t tween/fade them in, or at least manually adjust the Transparency property rather than using tweens.
  • If theres <1000 foliage items (each with 3-5 parts), then it won’t have as much of a performance drag as you would think, especially if they’re primitive parts. You could just leave these visible without distance filtering.
3 Likes

Tweens would be what he actually wants here. You should be refraining from directly adjusting properties on mass in loops wherever possible and tweens offload that to the engine side of things, where it can happen more performantly

In fact, I did a quick test modifying it to tween things instead of manually adjusting like he currently does and performance increased significantly, the slowdowns then came from finding the closest foliage regions when there is more than one island.

I also noticed @nate213121 that foliage just completely fails to initialize itself in any scenario where the island’s “Ready” marker is replicated before the rest of the island is replicated, you should be running the scatterOnCap function on newly added children to the slabs folder as well, not just once on all initial children.

1 Like

Alright, thank you for the feedback!

I fixed three things in the client foliage system:

-Fades now use TweenService instead of manually rewriting every part’s transparency each frame, which I believe fixes things because it takes it off of the main thread.
-The visibility check now only recalculates when the camera moves.
-Foliage now scatters onto grass caps as they replicate rather than in a single pass, so it no longer fails to appear when the island’s “Ready” marker reaches the client before the terrain does.

On an unrelated note, I also fixed the water by simply dividing the ocean into 2048x2048 chunks so roblox can handle them properly.

1 Like

I mean the queries right now are effectively O(1), and with octrees it would probably go to O(log n). The foliage is 2D data (only on the surface, I don’t mind their Y positions), so quadtrees will be more relevant in this situation I think. But yeah, it would be a great idea if the query sizes were varied or the foliage is very unevenly spread.