I’m seeing a large boost in performance here is a demo project
multi thread terrain.rbxl (33.5 KB)
and this is the code in the demo project
if game:IsLoaded() == false then game.Loaded:Wait() end
local chunkSize = 16
local actorAmount = 8 -- change this to have more actors more actors will allow more chunks to load per frame
local selectedActor = nil
local positionX = math.huge
local positionZ = math.huge
local actors = {game.ReplicatedFirst.Actor}
local loaded = {}
for i = 2, actorAmount do
local actor = actors[1]:Clone()
actor.Parent = actors[1].Parent
table.insert(actors, actor)
end
local function LoadChunk(chunkX, chunkZ)
if loaded[chunkX] == nil then loaded[chunkX] = {} end
if loaded[chunkX][chunkZ] ~= nil then return end
loaded[chunkX][chunkZ] = true
actors[selectedActor].Event:Fire(chunkX, chunkZ)
selectedActor += 1
if selectedActor > actorAmount then task.wait() selectedActor = 1 end
end
while true do
task.wait()
local chunkX = math.floor(workspace.CurrentCamera.Focus.Position.X / 4 / chunkSize)
local chunkZ = math.floor(workspace.CurrentCamera.Focus.Position.Z / 4 / chunkSize)
if positionX == chunkX and positionZ == chunkZ then continue end
positionX, positionZ, selectedActor = chunkX, chunkZ, 1
local directionX, directionZ, count, length = 1, 0, 0, 1
LoadChunk(chunkX, chunkZ)
for i = 2, 900 do -- this loop can be optimized
chunkX += directionX chunkZ += directionZ count += 1
if count == length then count = 0 directionX, directionZ = -directionZ, directionX if directionZ == 0 then length += 1 end end
LoadChunk(chunkX, chunkZ)
end
end
-- this is not optimized just some demo code
local chunkSize = 16
script.Parent.Event.Event:ConnectParallel(function(chunkX, chunkZ)
local startX = chunkX * chunkSize
local startZ = chunkZ * chunkSize
local endX = startX + chunkSize - 1
local endZ = startZ + chunkSize - 1
local region = Region3.new(Vector3.new(startX * 4, -16 * 4, startZ * 4), Vector3.new(endX * 4 + 4, 0, endZ * 4 + 4))
local materials, occupancys = game.Workspace.Terrain:ReadVoxels(region, 4)
for x = 1, materials.Size.X do
for z = 1, materials.Size.Z do
local height = 8 + math.noise((startX + x) * 0.04, 0, (startZ + z) * 0.04) * 6
for y = 1, materials.Size.Y do
if y > height then continue end
materials[x][y][z] = Enum.Material.Grass
occupancys[x][y][z] = 1
end
end
end
task.synchronize()
game.Workspace.Terrain:WriteVoxels(region, 4, materials, occupancys)
end)
you can change the actorAmount
to adjust how many chunks to load per frame
the default value of 8 means it will load a max of 8 16 by 16 chunks per a single frame its safe to try larger values if you like for instance if you set actorAmount
to 32 that will make it load a total of 32 16 by 16 chunks per a single frame
for me even just having 2 actors is fast enough
with 6 actors I can load 30 16 by 16 chunks in just 5 frames and leaving plenty of CPU for remaining game logic before it would of been imposable to load 6 16x16 chunks of terrain in a single frame without frame spikes