Randomly Creating and Placing Parts on Procedurally Generated Terrain

Hey there!

I’m working on a Mars game, where you explore the surface as a rover. The terrain is procedurally generated with the following script (a slightly modified version of the devhub one):

local Players = game:GetService("Players")

------------------------------------------------------------------------------------------------------------------------------------------------

local BASE_HEIGHT 		= 10				-- The main height factor for the terrain.
local CHUNK_SCALE 		= 8 				-- The grid scale for terrain generation. Should be kept relatively low if used in real-time.
local RENDER_DISTANCE 	= 500 / 2 			-- The length/width of chunks in voxels that should be around the player at all times
local X_SCALE 			= 300 / 4			-- How much we should strech the X scale of the generation noise
local Z_SCALE 			= 300 / 4			-- How much we should strech the Z scale of the generation noise
local GENERATION_SEED	= math.random() 	-- Seed for determining the main height map of the terrain.

------------------------------------------------------------------------------------------------------------------------------------------------
local chanceDebounce = false
local chunks = {}

local function chunkExists(chunkX, chunkZ)
	if not chunks[chunkX] then
		chunks[chunkX] = {}
	end
	return chunks[chunkX][chunkZ]
end

local function mountLayer(x, heightY, z, material)
	local beginY = -BASE_HEIGHT
	local endY = heightY
	local cframe = CFrame.new(x * 4 + 2, (beginY + endY) * 4 / 2, z * 4 + 2)
	local size = Vector3.new(4, (endY - beginY) * 4, 4)
	workspace.Terrain:FillBlock(cframe, size, material)	
end

function makeChunk(chunkX, chunkZ)
	local rootPosition = Vector3.new(chunkX * CHUNK_SCALE, 0, chunkZ * CHUNK_SCALE)
	chunks[chunkX][chunkZ] = true -- Acknowledge the chunk's existance.
	for x = 0, CHUNK_SCALE - 1 do
		for z = 0, CHUNK_SCALE - 1 do
			local cx = (chunkX * CHUNK_SCALE) + x
			local cz = (chunkZ * CHUNK_SCALE) + z
			local noise = math.noise(GENERATION_SEED, cx / X_SCALE, cz / Z_SCALE)
			local cy = noise * BASE_HEIGHT + 15
			local chance = math.random(1,50)
			
			
			if chance >= 1 and chance <= 2 then
				mountLayer(cx, cy, cz, Enum.Material.Rock)
			else
				mountLayer(cx, cy, cz, Enum.Material.Limestone)
			end
		end
	end
end

function checkSurroundings(location)
	local chunkX, chunkZ = math.floor(location.X / 4 / CHUNK_SCALE), math.floor(location.Z / 4 / CHUNK_SCALE)
	local range = math.max(1, RENDER_DISTANCE / CHUNK_SCALE)
	for x = -range, range do
		for z = -range, range do
			local cx, cz = chunkX + x
			local cz = chunkZ + z
			if not chunkExists(cx, cz) then
				makeChunk(cx, cz)
			end
		end
	end
end

while true do
	for _, player in pairs(workspace:GetDescendants()) do
		if player:IsA("Humanoid") then
			local humanoidRootPart = player.Parent:FindFirstChild("HumanoidRootPart")
			if humanoidRootPart then
				checkSurroundings(humanoidRootPart.Position)
			end
		end
	end
	wait(1)
end

The main problem I find myself facing is that I want to also randomly generate rocks, which would be parts, scattered around on the surface of the generated terrain. Being a not very advanced scripter, I don’t have any idea of how to do this, so I seek help from the rest of you!
I appreciate any and all help!

1 Like

Im guessing you could also use the random number and create parts using your max Base Height or X and Y Scale. The placement wont be the best but its progress.

2 Likes