Tips for Optimizing a Block Generation Script

Hello everyone!

I am currently developing a game which involves an infinately generated tower of cubes/blocks in a vertical tower. The game will need to generate 10,000 blocks instantly when the player joins, and can at that point slow down but still generate.

The following script is an extremely simple version of the system I described, but it seems to be quite unoptimized at present. It currently generate 3,000 blocks quite fast and then slows down, as setting this threshhold to 10,000 causes immense amounts of lag.


-- SERVICES --
local tweenService = game:GetService("TweenService")


-- CONFIG --
local horizontalOffsets = {-20,0,20}
local verticalOffsets = {10,20}

local numberOfColors = 6
local blockColors = {
	Red = Color3.fromRGB(255,0,0),
	Blue = Color3.fromRGB(0,0,255),
	Yellow = Color3.fromRGB(255,255,0),
	Orange = Color3.fromRGB(255,128,0),
	Green = Color3.fromRGB(0,200,0),
	Purple = Color3.fromRGB(255,0,255)
}

local numberOfBlocks = 1000000000


-- VARS --
local blocks = workspace.Blocks


-- MAIN --
local function generateBlocks()
	for i = 1,numberOfBlocks do
		if #workspace.Blocks:GetChildren() < 3_000 then
			if i % 50 == 0 then
				task.wait()
			end
		else
			task.wait(0.1)
		end
		
		local xOffset = horizontalOffsets[math.random(1,#horizontalOffsets)]
		local yOffset = verticalOffsets[math.random(1,#verticalOffsets)]
		local zOffset = horizontalOffsets[math.random(1,#horizontalOffsets)]

		local blockColorName = "Red"
		local blockColor3 = Color3.fromRGB(255,0,0)
		local index = 0
		local randIndex = math.random(1,numberOfColors)

		for cName,cValue in pairs(blockColors) do
			index += 1

			if index == randIndex then
				blockColorName = cName
				blockColor3 = cValue
			end
		end

		if xOffset == 0 and zOffset == 0 then
			if math.random(1,2) == 1 then
				xOffset = if math.random(1,2) == 1 then -20 else 20
			else
				zOffset = if math.random(1,2) == 1 then -20 else 20
			end
		end

		local blockTemplate = blocks:GetChildren()[#blocks:GetChildren()] or blocks.Template

		local newBlock = blockTemplate:Clone()
		newBlock.Parent = blocks
		newBlock.Name = blockColorName
		newBlock.Color = blockColor3

		newBlock.Position = Vector3.new(
			newBlock.Position.X + xOffset,
			newBlock.Position.Y + 10,
			newBlock.Position.Z + zOffset
		)

		for _,blk in pairs(blocks:GetChildren()) do
			if newBlock ~= blk and newBlock.Position.X == blk.Position.X and newBlock.Position.Z == blk.Position.Z then
				local heightDifference = newBlock.Position.Y - blk.Position.Y

				if heightDifference < 40 then
					newBlock:Destroy()
				else
					game.ReplicatedStorage.Values.Blocks.Value = #workspace.Blocks:GetChildren()
				end
			end
		end

		if math.abs(newBlock.Position.X - blocks.Template.Position.X) > 150 or math.abs(newBlock.Position.Z - blocks.Template.Position.Z) > 150 then
			newBlock:Destroy()
		end
	end
end

generateBlocks()

If anyone is able to provide advice, please do. Thank you so much in advance!

1 Like

Is there a greedymeshing algorithm being used? Cost benefit analysis: you reduce the overall part count (and thus the time it takes to physically load in all the blocks) at the cost of doing more computations. But it is worth it because the latter can be optimized in various ways, such as native code compilation (Native Luau) and parallelization (Parallel Luau). Reducing the part count also helps with memory and GPU usage. Another thing you can do is level of detail, where you decrease the resolution of the world (literally spawn in fewer, larger blocks) the farther away they are from the camera.

Greedymeshing example: