Couldn’t find better place to put this.
This code is from one of the developer articles and procedurally generates environments. I don’t fully understand it so can someone tell me exactly what the things do?
What I think I understand:
The code creates a box around the player and then generates the terrain and puts it in a table. It checks every 1 second if a player moves to another area and checks if the area is inside the table. If not, it creates it.
What I don’t understand:
The maths of it. E.g. why render distance divided by chunk scale, why does chunkx have to be multiplied by chunk scale. why is chunk scale required, etc.
If you don’t get what I mean, just explain what you think I don’t get
local Players = game:GetService("Players")
------------------------------------------------------------------------------------------------------------------------------------------------
local BASE_HEIGHT = 10 -- The main height factor for the terrain.
local CHUNK_SCALE = 3 -- The grid scale for terrain generation. Should be kept relatively low if used in real-time.
local RENDER_DISTANCE = 120 / 4 -- 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 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
mountLayer(cx, cy, cz, Enum.Material.Grass)
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(Players:GetPlayers()) do
if player.Character then
local humanoidRootPart = player.Character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart then
checkSurroundings(humanoidRootPart.Position)
end
end
end
wait(1)
end