Howdy developers!
I am working on a procedurally generated game (kind of like minecraft), in which I use perlin noise to generate the chunks.
With a normal script, it takes ~1000ms to generate one chunk. I’ve tried using actors, but it seems they create more lag than they reduce (It takes 2 seconds per chunk, and lags the entire server).
This is the script:
function Terrain:GenerateChunk(chunkPosition, onFinished)
local chunkNeighbors = {}
for neightbor_x = -1, 1 do
for neightbor_z = -1, 1 do
for neightbor_y = -1, 1 do
if neightbor_x ~= 0 or not (neightbor_x == neightbor_y and neightbor_x == neightbor_z and neightbor_z == neightbor_y) then
local neighbor_position = Vector3.new(chunkPosition.X + neightbor_x, chunkPosition.Y + neightbor_y, chunkPosition.Z + neightbor_z)
table.insert(chunkNeighbors, neighbor_position)
end
end
end
end
local chunk = {
position = chunkPosition,
blocks = {},
neighbors = chunkNeighbors,
}
local start_x = Terrain.chunk_size.X * chunkPosition.X
local end_x = (Terrain.chunk_size.X) * (chunkPosition.X + 1)
local start_z = Terrain.chunk_size.Z * chunkPosition.Z
local end_z = (Terrain.chunk_size.Z ) * (chunkPosition.Z + 1)
for x = start_x, end_x do -- I suspect this is the reason for the lag
for z = start_z, end_z do
if chunkPosition.Y == 0 then
local max_y = math.floor((math.noise(x/self.scale, z/self.scale, self.seed) * self.amplitude) + 100)
local max_block_y = chunkPosition.Y * Terrain.chunk_size.Y + max_y
for y = chunkPosition.Y * Terrain.chunk_size.Y, max_block_y do
local material = "unknown"
if y < max_block_y - 5 then
material = "stone"
else
material = "grass"
end
local blockPosition = Vector3.new(x, y, z)
local block = {
position = blockPosition,
visible = false,
rendered = false,
render_part = nil,
neighbors = {},
material = material,
}
chunk.blocks[blockPosition] = block
end
for y = max_block_y, ((chunkPosition.Y + 1) * Terrain.chunk_size.Y) do
local blockPosition = Vector3.new(x, y, z)
local block = {
position = blockPosition,
visible = false,
rendered = false,
render_part = nil,
neighbors = {},
material = "air",
}
chunk.blocks[blockPosition] = block
end
else
end
end
if x % 5 == 0 then
task.wait()
end
end
for x = start_x, end_x do
for z = start_z, end_z do
for y = (chunkPosition.Y * Terrain.chunk_size.Y), ((chunkPosition.Y + 1) * Terrain.chunk_size.Y) do
local block = chunk.blocks[Vector3.new(x, y, z)]
if x == start_x or x == end_x or z == start_z or z == end_z then
block.visible = true
end
for neightbor_x = -1, 1 do
for neightbor_z = -1, 1 do
for neightbor_y = -1, 1 do
if neightbor_x ~= 0 or not (neightbor_x == neightbor_y and neightbor_x == neightbor_z and neightbor_z == neightbor_y) then
local neighbor_position = Vector3.new(x + neightbor_x, y + neightbor_y, z + neightbor_z)
table.insert(block.neighbors, neighbor_position)
if block.material ~= "air" then
local real_block = chunk.blocks[neighbor_position]
if real_block and real_block.material == "air" then
block.visible = true
end
end
end
end
end
end
end
end
if x % 5 == 0 then
task.wait()
end
end
--task.synchronize()
self.chunks[chunkPosition] = chunk
onFinished()
end