Realistic Infinite Terrain

I’ve recently gotten really into experimenting with Perlin Noise and similar stuff. I’ve made a few scripts for creating terrain, specifically using Roblox’s built-in terrain system instead of blocks or shapes. But here’s the thing: I’m trying to add different environments, kind of like what you find in Minecraft, but using Roblox’s terrain. I want to have oceans, small ponds, lakes, rivers, caves, mountains, and more.

I’m also curious about how to make different layers of stuff underground and have the terrain change as players dig, just like those mining games with never-ending digging. It’ll be like having RTX Minecraft, and once i have the terrain down, scripting things like finding ores should be easier

So, if You would like to help or you know where I can learn more about it, please drop me a message!

1 Like

Basically you mix different noises until it looks cool, theres not that much more specific guidance out there unless you want a minecraft style specifically, in which case you could look at the code for a minecraft mod that adds new terraingen.
When you want globs, you chop the top of a noise function off, so that greater than a certain value enables generation (of something like ore) and less than disables it.

I did try mixing different noises i did a lake layer, a mountain layer and temperature layer which worked but the mountains didnt mix with the regular layer of perlin noise and lakes looks so bad

Terrain generation has so many goals, like the floor elevation, trees, plants, rocks, or even little detail, like flowers.

The floor elevation is the most difficult part, especially if you want to make it smooth, so you can try to ignore that.

Here’s a little template script you can put in ServerScriptService that generates random parts around the map:

local partA = workspace.PartA --Point A.
local partB = workspace.PartB --Point B.

local amount = 50 --Amount of parts to generate.

for i=1,amount do
    
    local part = Instance.new("Part", workspace)
    part.Name = tostring(i)
    part.Anchored = true
    part.Size = Vector3.new(2,2,2)
    
    part.CFrame = CFrame.new(Vector3.new(math.random(partA.Position.X,partB.Position.X),1,math.random(partA.Position.Z,partB.Position.Z)))
    
end

I obviously haven’t tested this yet, so let me know if there’s any errors: