How do I speed this up?

So I have this game, where it randomly loads up prebuilt models and places them into select positions. This function of the game works, but it takes SUPER long to load up the map. It can take up to 7-8 minutes to load up the map, and I want to know how to speed it up.

SCRIPT






local ServerStorage = game.ServerStorage
local ReplicatedStorage = game.ReplicatedStorage

local module = require(game.ServerStorage.RandomGen)
local tabel = {}
howmanyinexist = 0
numcap = (30 * 4)
rowcap = (32 * 4)
local row = 0
local num = -1
local done = false



while true do
	local new
	--num = num + 1; 
	num += 1;
	local chances = module.GenerateRandom()
	if chances == nil then
		new = ServerStorage.Plots["Empty Area"]:Clone()
	end
	if chances ~= nil then
		local find = ServerStorage.Plots:FindFirstChild(chances)
		if find ~= nil then
			howmanyinexist = howmanyinexist + 1
			new = find:Clone()
			new:SetAttribute("Position",Vector3.new(985,0.5,985) - Vector3.new(65 * num, 0, 65 * row))
			if math.random(1,95) ~= 5 then
				new.Name = ""..new.Name.." #"..howmanyinexist..""
			else
				new.Name = "Unidentified Plot #"..howmanyinexist..""
			end
			new.Parent = workspace.RandomlyGenPlots
			new:SetAttribute("Position",Vector3.new(985,0.5,985) - Vector3.new(65 * num, 0, 65 * row))
			local pivotDestination = CFrame.new(Vector3.new(985,0.5,985) - Vector3.new(65 * num, 0, 65 * row),Vector3.new(0,0,0))
			new:PivotTo(pivotDestination)
			new.Parent = game.Lighting.Creating
			local s=module.returncomp(chances)
			--print(s)
			if s == true then
				--print("Ok!")
				--table.insert(tabel,new)
				--	ReplicatedStorage.Remotes.HideUntilNearby:FireAllClients(new,(Vector3.new(-985, 0.5, -985) + Vector3.new(65 * num, 0, 65 * row)))
			end
			if s == false then
				--nothing
			end
		end
	end
	if num >= numcap then
		--row = row + 1;
		row += 1;
		num = -1 
	end
	task.wait()
	if row >= rowcap then
			game.Lighting.WaitingForPlotLoad.Value = true
			break
	end
end
local rs = game:GetService("RunService")
local ServerStorage = game.ServerStorage
local ReplicatedStorage = game.ReplicatedStorage

local module = require(game.ServerStorage.RandomGen)
local tabel = {}
howmanyinexist = 0
numcap = (30 * 4)
rowcap = (32 * 4)
local row = 0
local num = -1
local done = false



rs.Heartbeat:Connect(function()
	local new
	--num = num + 1; 
	num += 1;
	local chances = module.GenerateRandom()
	if chances == nil then
		new = ServerStorage.Plots["Empty Area"]:Clone()
	end
	if chances ~= nil then
		local find = ServerStorage.Plots:FindFirstChild(chances)
		if find ~= nil then
			howmanyinexist = howmanyinexist + 1
			new = find:Clone()
			new:SetAttribute("Position",Vector3.new(985,0.5,985) - Vector3.new(65 * num, 0, 65 * row))
			if math.random(1,95) ~= 5 then
				new.Name = ""..new.Name.." #"..howmanyinexist..""
			else
				new.Name = "Unidentified Plot #"..howmanyinexist..""
			end
			new.Parent = workspace.RandomlyGenPlots
			new:SetAttribute("Position",Vector3.new(985,0.5,985) - Vector3.new(65 * num, 0, 65 * row))
			local pivotDestination = CFrame.new(Vector3.new(985,0.5,985) - Vector3.new(65 * num, 0, 65 * row),Vector3.new(0,0,0))
			new:PivotTo(pivotDestination)
			new.Parent = game.Lighting.Creating
			local s=module.returncomp(chances)
			--print(s)
			if s == true then
				--print("Ok!")
				--table.insert(tabel,new)
				--	ReplicatedStorage.Remotes.HideUntilNearby:FireAllClients(new,(Vector3.new(-985, 0.5, -985) + Vector3.new(65 * num, 0, 65 * row)))
			end
			if s == false then
				--nothing
			end
		end
	end
	if num >= numcap then
		--row = row + 1;
		row += 1;
		num = -1 
	end
	task.wait()
	if row >= rowcap then
			game.Lighting.WaitingForPlotLoad.Value = true
			break
	end
end)

Considering while true do isn’t efficient, this might be the easiest fix that could help you with performance. I have to go soon so I couldn’t look into your code on a deeper level. I can later though.

This is probably because you are yielding every step. That task.wait() is going to run every time and isn’t needed nearly that frequently. This adds up to a lot of wasted time. You might be able to get away with not waiting at all of the algorithm is fast enough. If you want to play it safe though, use some conditional yielding.

--put this line outside the loop
local t = tick()

--replace your task.wait with these lines.  Adjust the 0.2 to determine how long it waits before yielding.  0.2 is almost certainly too high if your algorithm will take a while though since this is where it allows other parts of the game to run.
if tick() - t > 0.2 then
    task.wait()
    t = tick()
end
Not directly related to your problem, but might be worth reading

Not directly related but from my skimming it seems for loops might have been a better choice for this algorithm, but it isn’t worth rewriting it so long as its termination is certain.

Also. This is your break case:

if row >= rowcap then
			game.Lighting.WaitingForPlotLoad.Value = true
			break
	end

It could be written into the loop itself which can help with reading it. But this is really a small style thing.

So like this

while not (row >= rowcap) do --you have to invert the statement somehow because loops only run when it’s true. You could also do row < rowcap instead of a not. 
    --	your code
end
game.Lighting.WaitingForPlotLoad.Value = true --update this when the loop ends.

That just makes it so you don’t have to have an if statement to handle the major break case which can make it easier to see at a glance what terminates the loop.

here is some demo code that might help you simplify your code

-- get all the models in the plots folder
local plots = game.ServerStorage.Plots:GetChildren()
-- a vector3 describing the plots offset
local offset = Vector3.new(500, 0.5, 500)
-- space between plots
local spacing = 65

for x = 1, 120 do
	for z = 1, 120 do
		-- calculate the plots CFrame
		local cFrame = CFrame.new(x * spacing, 0, z * spacing) + offset

		-- clone a random plot
		local plot = plots[math.random(#plots)]:Clone()
		-- position the plot
		plot:PivotTo(cFrame)
		-- place the plot into RandomlyGenPlots
		plot.Parent = workspace.RandomlyGenPlots
	end

	-- wait for 1 frame to stop the game from freezing 
	task.wait()
end
1 Like

The code will run significantly faster if you move the wait into the outer for loop or only allow yielding on multiples of 10 or something since the game can handle more than one step before yielding. But otherwise it’s a really good approach.

correct it depends greatly on how complex the models op is cloning are to know how many its safe to clone in 1 heartbeat

120 * 120 = 14400 models
task.wait() normally waits for around 0.0166666666667 seconds

so this loop will take over 239.9999999 seconds to finish

if op only waits on outer loop then it would take around 1.9999999992 seconds to finish

i updated the script above to wait on the outer loop op will need to experiment to find a good balance

1 Like

I slept, but thank you 3 for helping me figure out a way to speed up the game! It loads up in under a minute now, and that’s fine to me.