I am attempting to create a block game, (Voxel game - Roblox) and I want to make the terrain generate randomly, like hills. Currently all it does is take a group of blocks and clone it until it fills ~the size of the baseplate.
Each block is 3x3x3, and I want the terrain to be made up of them. How would I go about this?
@MrSprinkleToes Don’t use the other script, use this one instead:
local Players = game:GetService("Players")
------------------------------------------------------------------------------------------------------------------------------------------------
local BASE_HEIGHT = 10 -- The main height factor for the terrain.
local CHUNK_SCALE = 1 -- The grid scale for terrain generation. Should be kept relatively low if used in real-time.
local RENDER_DISTANCE = 25 -- The length/width of chunks in voxels that should be around the player at all times
local X_SCALE = 90 / 4 -- How much we should strech the X scale of the generation noise
local Z_SCALE = 90 / 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 chunks = {}
local function roundToOdd(n)
--spawn(function()
return math.floor(n - n % 3);
--end)
end
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 * 3 + 1, roundToOdd((beginY + endY) * 3 / 1), z * 3 + 1)
local size = Vector3.new(3, (endY - beginY) * 3, 3)
local p = Instance.new("Part", workspace)
p.Anchored = true
p.CFrame = cframe
p.Size = Vector3.new(3, 3, 3)
p.Material = Enum.Material.Grass
p.BrickColor = BrickColor.new("Forest green")
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
mountLayer(cx, cy, cz, Enum.Material.Grass)
end
end
end
function checkSurroundings(location)
local chunkX, chunkZ = math.floor(location.X / 3 / CHUNK_SCALE), math.floor(location.Z / 3 / 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
game:GetService("RunService").Heartbeat:Connect(function()
for _, player in pairs(Players:GetPlayers()) do
if player.Character then
local humanoidRootPart = player.Character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart then
checkSurroundings(humanoidRootPart.Position)
end
end
end
end)
Just curious, I’ve been trying to figure this out for a while. I am using this in places created with the createplace api and saving these places with the saveplace api. How would I prevent the game from recreating chunks that were already created and saved in the place? Because of it recreating chunks when the person rejoins the game, it doesn’t save changes made to the terrain. (You can see it in action if you create a place in my game when you first join, then rejoin the place)
I know this topic is 2 years old, but how would you make it so you can detect parts out of a range. I tried doing something with my script, but it would delete all blocks out of that range if I move out of it (if that makes sense).