Need Help Optimizing this Capture Point Script

So this is a script I have in my game, in where every 10 minutes or so, a game mode will launch where players can capture down a point in the game, and get a ton of cash for doing so. The script can be fairly laggy for console and mobile players, and I’m looking to see if there’s any way I can optimize it. The script uses a changed event to detect when a game has begun or ended, and then there is a while loop inside it to down countdowns, detect when people have touched (or stopped touching) the capture point, etc.

local notif = game.ReplicatedStorage:WaitForChild("Remote"):WaitForChild("SystemMessage")
local flag2 = script.Parent.flag:Clone()
wait(1)
script.Parent.flag:Destroy()
local fun = script.Parent.game
local choosy = { ---- setting up islands
		
}
local Time = 600
for model,isl in pairs (script.Parent.island:GetChildren()) do
	if isl:IsA("Model") then --- looks for anything inside a folder that has potential capture poinr locations
		local folder = isl:FindFirstChild("spots")
		if folder ~= nil then
			for a,b in pairs(isl.spots:GetChildren()) do
				table.insert(choosy,b)
			end
		end
	end
end

fun.Changed:Connect(function(val)
	local fiver = false
	local thirty = false
	if val == true then
		local num = math.random(1,#choosy)
		local pick_Me = choosy[num]
		local cash = math.random(33000,99000)
		local Defender = nil
		local msg = 
			"[MISSION]: Soldiers, hold down "..pick_Me.Name.." at "..pick_Me.Parent.Parent.Name.." for 3 minutes to earn $"..cash.."!"
		notif:FireAllClients(msg,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
		local flag = flag2:Clone()
		flag.Position = pick_Me.Position
		flag.Parent = pick_Me.Parent
		flag.touch.Position = flag.Position
		flag:MakeJoints()
		script.sec.Changed:Connect(function(number)
			if number == 0 and flag ~= nil and flag.Holder ~= nil then
				local winner = flag.Holder.Value
				local ms = "[MISSION]: "..winner.Name.." has won the $"..cash.."!"
				notif:FireAllClients(ms,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
				flag:Destroy()
				for i,v in pairs(game.Players:GetChildren()) do
					if v.Team == winner then
						v.leaderstats.Cash.Value = v.leaderstats.Cash.Value + cash
					end	
				end
				fun.Value = false
			end
		end)
		flag.touch.Touched:Connect(function()end) -- Can-collide false parts need a TouchIntere
		local function getCollidingPlayers(part)
			local colliding = {}
			for _,obj in pairs(part:GetTouchingParts()) do
				local plr = game.Players:GetPlayerFromCharacter(obj.Parent) -- Check if colliding part is a character's part
				local found = false
				for _,cPlr in pairs(colliding) do -- Make sure they're not already in the list
					if cPlr == plr then
						found = true
						break
					end
				end
				if not found then
					table.insert(colliding,plr) -- Add them to the list
				end
			end
			return colliding
		end
		local defending = false
		local count = 0
		local neutral = "http://www.roblox.com/asset/?id=160803208"
		while fun.Value == true do
			wait(1)
			local colliding = getCollidingPlayers(flag.touch)
			local count2 = 0
			if #colliding > 0 then
				for _,plr in ipairs (colliding) do
					-- Do stuff to all colliding players
					if plr.Team == Defender then
						count2 = count2 + 1
						defending = true
						if flag.Holder.Value == nil then
							msg = "[MISSION]: "..plr.Team.Name.." has recaptured "..flag.Parent.Parent.Name.."!"
							notif:FireAllClients(msg,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
						end
						flag.notif.flag.Image = ""..plr.Team.flag.Texture
						flag.Holder.Value = Defender
					elseif 	plr.Team ~= flag.Holder.Value then
						if defending == false then
							msg = "[MISSION]: "..plr.Team.Name.." has captured "..flag.Parent.Parent.Name.."!"
							notif:FireAllClients(msg,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
							flag.Holder.Value = plr.Team
							Defender = plr.Team
							script.sec.Value = 180
							flag.BrickColor = plr.Team.TeamColor
							flag.touch.SelectionBox.Color3 = plr.Team.TeamColor.Color
							flag.notif.flag.Image = ""..plr.Team.flag.Texture
							Defender = plr.Team
							count2 = count2 + 1							
						end
					end
				end
			else
				-- No one is colliding
				defending = false
				if flag.Holder.Value ~= nil then
					msg = "[MISSION]: "..flag.Holder.Value.Name.." has lost control of "..flag.Parent.Parent.Name.." by not being in its vicinity!"
					notif:FireAllClients(msg,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
					flag.Holder.Value = nil
					flag.notif.flag.Image = neutral
				end	
			end
			count = count2
			if count <= 0 then
				defending = false
				if flag.Holder.Value ~= nil then
					msg = "[MISSION]: "..flag.Holder.Value.Name.." has lost control of "..flag.Parent.Parent.Name.." by not being in its vicinity!"
					notif:FireAllClients(msg,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
					flag.Holder.Value = nil
					flag.notif.flag.Image = neutral
				end	
			end
			for i,v in pairs(game.Players:GetChildren()) do
				if v.Team == flag.Holder.Value then
					v.leaderstats.Cash.Value = v.leaderstats.Cash.Value + 20
				end	
			end
			if flag.Holder.Value ~= nil and script.sec.Value > 0 then
				script.sec.Value = script.sec.Value - 1
				flag.notif.countdown.Visible = true
				flag.notif.countdown.Text = ""..script.sec.Value
			else
				flag.notif.countdown.Visible = false
			end			
			if Time > 0 and flag.Holder.Value == nil then
				Time = Time - 1
			end
			if Time == 300 and fiver == false then
				msg = "[MISSION]: Five Minutes Remain!"
				notif:FireAllClients(msg,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
				fiver = true
			elseif Time == 30 and thirty == false then
				msg = "[MISSION]: Thirty Seconds Remain!"
				notif:FireAllClients(msg,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
				thirty = true
			elseif Time <= 0 then
				fun.Value = false
				Time = 600
				local ms = "[MISSION]: Time's up! No one held down the mission in time!"
				notif:FireAllClients(ms,Enum.FontSize.Size24,Enum.Font.ArialBold,Color3.fromRGB(255, 255, 255))
				flag:Destroy()
			end
		end
	elseif val == false then
		script.sec.Value = 180
		wait(math.random(600,900))
		fun.Value = true	
	end
end)

Hi!

The very first thing I noticed is that you used table.insert which leaves a lot of room to be optimized!

Try to replace table.insert with table[#table + 1] = value where possible.
I am sure you knew this already, but just to clarify: the # in front of a table returns its length.

I also see that you used the touch event which might become a little laggy if a player character is involved. It can fire a lot of times due to the idle animation moving the player up and down. If the player is moving it fires multiple times a second.

P.S. You used a lot of if statements. Might want to find a way to reduce them. If (no pun intended :wink: ) I remember correctly, Lua goes through if statments even if the condition is false. It just doesn’t execute what’s inside the if statements.

How could I reduce the if statements?

Sorry for the late response, I was quite busy yesterday. I can see that this is a script in a Capture the Flag game, if I may ask, are you checking who’s on the point (if I gathered that correctly from the code) by using .Touched?

I suggest you make a local script that shoots a down to check what the player is standing on. If the player is standing on the platform, fire a event.

For the while loop, instead of checking every condition every second, I suggest creating a coroutine that counts down and doesn’t do anything else in the if statements other than trigger functions for the other things (such as triggering the notif event)