How can I use parallel lua scripting to improve performance of terrain generation

  1. I want to implement parallel lua into my terrain generation. How can I do that?

  2. Terrain Generation takes forever two load.

  3. I have tried implementing parallel from other posts but I can’t get it to work.

-- Here is the terrain generation code: local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

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

local ChunkScale = 2 -- The grid scale for terrain generation. Should be kept relatively low if used in real-time.
local SearchRange = 1000
local seed,seed2,seed3	= math.random(0,100000000),math.random(0,100000000),math.random(0,100000000) 	-- Seed for determining the main height map of the terrain.

local Elevation =  1

local noiseScale = 20
local amplitude = 20

local noiseScale2 = 100
local amplitude2 = 60

local GenerationSpeed = 100
------------------------------------------------------------------------------------------------------------------------------------------------
local chunks = {}

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

local function CheckTop(Points,x,y,z)
	for _,v in pairs(Points) do
		if v then
			if x == v.X and z == v.Z then
				for n = 1,3 do
					if y == v.Y-n then
						return true
					end
				end
			end
		end
	end
end

--local YScale = 200 --200
function makeChunk(chunkX, chunkZ)
	task.synchronize()
	local rootPosition = Vector3.new(chunkX * ChunkScale, 0, chunkZ * ChunkScale)
	local Points = {}
	chunks[chunkX][chunkZ] = true -- Acknowledge the chunk's existance.
	for x = 0, ChunkScale - 1 do
		for z = 0, ChunkScale - 1 do
			local cx = (chunkX * ChunkScale) + x
			local cz = (chunkZ * ChunkScale) + z

			local Yscalenoiose1 = math.noise(cx/200, cz/200, math.floor((seed+seed2+seed3)/3))
			local Yscalenoiose2 = math.noise(cx/50, cz/50, math.floor((seed+seed2+seed3)/3)+1000)/10

			local YScaleNoise = Yscalenoiose1+Yscalenoiose2
			local YScale = 50 + math.floor(math.abs(YScaleNoise)*150)
			for y = 0, YScale do
				local cy = (ChunkScale) + y

				local xNoise = math.noise(cy/noiseScale, cz/noiseScale, seed) * amplitude
				local yNoise = math.noise(cx/noiseScale, cz/noiseScale, seed2) * amplitude
				local zNoise = math.noise(cx/noiseScale, cy/noiseScale, seed3) * amplitude

				local xNoise2 = math.noise(cy/noiseScale2, cz/noiseScale2, seed) * amplitude2
				local yNoise2 = math.noise(cx/noiseScale2, cz/noiseScale2, seed2) * amplitude2
				local zNoise2 = math.noise(cx/noiseScale2, cy/noiseScale2, seed3) * amplitude2

				local density = (xNoise + yNoise + zNoise)+(xNoise2 + yNoise2 + zNoise2) - y + Elevation
				if density > -20 then
					if y == YScale then
						table.insert(Points,Vector3.new(cx,cy,cz))
					end
				end

				if density < -15 then --   -15
					if y == 0 then
						table.insert(Points,Vector3.new(cx,cy,cz))
					end
					if density > -20 then
						table.insert(Points,Vector3.new(cx,cy,cz))
					end
				end
			end
		end
	end

	local d = 0
	for i,v in pairs(Points) do
		if v then
			local cx,cy,cz = v.X,v.Y,v.Z
			local Material = Enum.Material.Sand
			local CheckT = CheckTop(Points,cx,cy,cz)
			if CheckT == nil then
			elseif CheckT == true then
				Material = Enum.Material.Rock
			end

			workspace.Terrain:FillBlock(CFrame.new(cx*4,cy*4,cz*4),Vector3.new(4,4,4),Material)
		end
		if d > GenerationSpeed then d = 0
			RunService.Stepped:Wait()			
		else
			d = d + 1
		end
	end
end

local startTick = tick()

local chunkX, chunkZ = math.floor(0 / 4 / ChunkScale), math.floor(0 / 4 / ChunkScale)
local range = math.max(1, SearchRange/ChunkScale)
local ChunksMade = {}
for x = -range, range do
	for z = -range, range do
		local cx = chunkX + x
		local cz = chunkZ + z
		if not chunkExists(cx, cz) then
			table.insert(ChunksMade,{cx,cz})
		end
	end
end


for i,v in pairs(ChunksMade) do
	makeChunk(v[1], v[2])
end
1 Like

what if you, instead of creating two loops, use task.spawn() with makeChunk?

I will try it. Thank you for the advice.

1 Like

Ok well my computer freezes and it says Script timeout: exhausted allowed execution time .

I already tried implementing the code from this post How to optimize terrain loading? - #5 by Brickman808 , but I can’t get it to work.

In the brackets of task.spawn() - it must be empty for the fastest result, if the error still occurs make sure your code isn’t interfering and causing it.