Cleanup Function improvements?

I have a fully functioning roundSystem script which handles many key features of my game, including CFrames, Incrementing Of Values, etc. However, I’m not satisified fully with its state now, as it’s had a very bumpy past, constantly throwing errors, acting slow etc. One major factor, I believe, is the cleanup function.

I’ve had to clone/destroy models with hundreds of parts, in attempt to refresh the game once the round has occurred. This has lead to many script exhaustion time errors, and it’s disrupted gameplay heavily.

I managed to subdue the constant errors by introducing Runservice.Heartbeat:Wait and a lot of Waits but I still wonder if anything more can be done to optimize this (making it as fast as possible), to prevent long delays between rounds (Like I am experiencing at the moment.

Function

function CleanUp()
	workspace.Current.Part.SurfaceGui.TextLabel.Text = "Regenerating Map For Next Round"

	for i, v in pairs(workspace.SpleefMap:GetDescendants()) do
		if v:IsA("Part") then
			v:Destroy()
			game:GetService('RunService').Heartbeat:Wait()

		end
	end
	for i, v in pairs(workspace:GetChildren()) do
		if v.Name == "Portal" or v.Name =="UFO" or v.Name == "JumpPad" then
			v:Destroy()
			game:GetService('RunService').Heartbeat:Wait()

		end
	end
	local Clone = game.ServerStorage.SpleefMap:Clone()
	wait(1)

	game.ReplicatedStorage.GeneratingMap:FireAllClients(true)
	wait(8)
	print("Regenerating")
	game.ReplicatedStorage.Regenerating.Value = true
	Clone.Parent = workspace
	local chosenColor = BrickColor.Random()
	for i, v in pairs(Clone:GetDescendants()) do
		if v:IsA("Part") then
			v.BrickColor = chosenColor
			game:GetService('RunService').Heartbeat:Wait()

		end
	end
	wait(1)
	local ss = game.ServerStorage.PartTagger:Clone()
	ss.Parent = Clone
	wait()
	
	game.ReplicatedStorage.Regenerating.Value = false
	workspace.Current.Part.SurfaceGui.TextLabel.Text = ""

end

Waits in there are annoying for me, and I want to find a way to remove as many of them as possible, as these are preventing the errors, but they are provoking more time to wait, which is makes the game more tedious. Thanks!

1 Like

Possibly segment the waits by waiting every 2, 3, or 5 parts instead of every individual part so that it doesn’t take near as long? (will reduce the wait time by like 2, 3, or 5 times)
(Note you could maybe get away with 10 – might wanna test different speeds)

You can achieve this with the Modulus operator (%).

Example:

for i, v in pairs(Clone:GetDescendants()) do
	if (i % 3) == 0 then
		game:GetService('RunService').Heartbeat:Wait()
	end
	if v:IsA("Part") then
		v.BrickColor = chosenColor
	end
end

What is the Modulo operation?

“In computing, the modulo operation returns the remainder or signed remainder of a division, after one number is divided by another.”

Source: Modulo - Wikipedia

1 Like

I would recommend replacing the i in i, v in pairs() with an underscore (_) if you aren’t using it. I can also agree with Trayeus, you should try that.

1 Like

Does it affect anything, if I leave it as i ?

No. But I suggest you do not use pairs with normal tables. Use ipairs when iterating normal tables. If you do not use a variable in Lua it is a good rule to leave it as_ which means it is a placeholder variable.

1 Like
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local Hearbeat = RunService.Heartbeat

local WaitAmount = 20 -- On every nth iteration it will wait a bit.

function CleanUp()
	local TextLabel = workspace:FindFirstChild("Current"):FindFirstChild("Part"):FindFirstChild("SurfaceGui"):FindFirstChild("TextLabel")
	TextLabel.Text = "Regenerating Map For Next Round"

	workspace:WaitForChild("SpleefMap"):Destroy()
	
	for i, v in pairs(workspace:GetChildren()) do
		if v.Name == "Portal" or v.Name == "UFO" or v.Name == "JumpPad" then
			v:Destroy()
			if 1 % WaitAmount == 1 then
				Hearbeat:Wait()
			end
		end
	end
	
	local Clone = ServerStorage:FindFirstChild("SpleefMap"):Clone()
	Hearbeat:Wait()
	
	ReplicatedStorage:FindFirstChild("GeneratingMap"):FireAllClients(true)
	wait(8)
	print("Regenerating...")
	ReplicatedStorage:FindFirstChild("Regenerating").Value = true
	
	Clone.Parent = workspace
	local chosenColor = BrickColor.Random()
	for i, v in pairs(Clone:GetDescendants()) do
		if v:IsA("Part") then
			v.BrickColor = chosenColor
			if 1 % WaitAmount == 1 then
				Hearbeat:Wait()
			end
		end
	end
	wait(1)
	
	local New = ServerStorage:FindFirstChild("PartTagger"):Clone()
	New.Parent = Clone
	Hearbeat:Wait()

	ReplicatedStorage:FindFirstChild("Regenerating").Value = false
	TextLabel.Text = ""

end
1 Like

Another optimisation you could make is to avoid using :IsA when not comparing abstract classes (such as BasePart).

You should instead compare the .ClassName property

if somePart:IsA("Part") then -- slower

if somePart.ClassName == "Part" then -- fast

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

-- very slow
if somePart.ClassName == "Part" or somePart.ClassName == "MeshPart" or somePart.ClassName = ... then

-- much faster! (and cleaner too)
if somepart:IsA("BasePart") then

:IsA is aroud half the speed of just comparing the ClassName, but you should always use :IsA when comparing abstract classes

Ok, I will do! Thanks for telling me that. seeing as I was unaware IsA could have a performance impact

No… Just why lol. Optimizations like that are not helpful at all. That’s a 0.0001 micro-optimization. Optimizations such as the time complexity of your program should be taken more in consideration.

It doesn’t at all. (character limit)

1 Like

Thank you! It’s much faster when regenerating the map now!

1 Like

No problem, glad to hear!
If you need more help feel free to reach out!