Why function is spam when click button

hi im ctg i need help


im making tower defense game and when i active the ablity it spam 4 time and spawn 4 npc
i dont know why it spam

local function triggedAblity()
		warn("Work")
		for i, AblityButton in pairs(ui.Selection.UI.AblityFrame:GetChildren()) do
			if AblityButton:IsA("ImageLabel") then

				if selectTower:FindFirstChild("TimeAblity") then
					local TimeAblity = selectTower:FindFirstChild("TimeAblity")
					local ablityDebounce = false
					local AblityFrame = ui.Selection.UI.AblityFrame
					
					AblityFrame.AblityTrooper1.TextButton.MouseButton1Click:Connect(function()
						if selectTower.TimeAblity.Value == 1  then
							warn("Ablity")
							AblityFrame.AblityTrooper1.TextButton.Visible = false
							FuntionAblity:InvokeServer("AblityTrooper1", selectTower)
							wait(0.1)
							AblityFrame.AblityTrooper1.TextButton.Visible = true
						end
					end)
					
					AblityFrame.Oofer.TextButton.MouseButton1Click:Connect(function()
						if selectTower.TimeAblity.Value == 1 then
							ablityDebounce = true
							FuntionAblity:InvokeServer("Oofer", selectTower)
							wait(0.1)
							ablityDebounce = false
						end
					end)

					AblityFrame.AblityTrooper2.TextButton.MouseButton1Click:Connect(function()
						if selectTower.TimeAblity.Value == 1  then
							AblityFrame.AblityTrooper2.TextButton.Visible = false
							FuntionAblity:InvokeServer("AblityTrooper2", selectTower)
							wait(0.1)
							AblityFrame.AblityTrooper2.TextButton.Visible = true
						end
					end)

					AblityFrame.Homeless.TextButton.MouseButton1Click:Connect(function()
						if selectTower.TimeAblity.Value == 1  then
							AblityFrame.Homeless.TextButton.Visible = false
							FuntionAblity:InvokeServer("Homeless", selectTower)
							wait(0.1)
							AblityFrame.Homeless.TextButton.Visible = true
						end
					end)

					local HomelessTime = AblityFrame.Homeless:WaitForChild("Time", 0.1)
					local AblityTrooper1Time = AblityFrame.AblityTrooper1:WaitForChild("Time", 0.1)
					local AblityTrooper2Time = AblityFrame.AblityTrooper2:WaitForChild("Time", 0.1)
					local success, fail = pcall(function()
						TimeAblity.Changed:Connect(function(change)
							if selectTower then
								if selectTower.Name ==  "Homeless" then
									if TimeAblity.Value == 0 then
										HomelessTime.Visible = false
										AblityFrame.Homeless.TextButton.Visible = true
									else
										HomelessTime.Visible = true
										HomelessTime.Text = change
									end

								end


								if selectTower.Name ==  "Lieutenant Lv4" then
									if TimeAblity.Value == 0 then
										AblityTrooper1Time.Visible = false
										AblityFrame.AblityTrooper1.TextButton.Visible = true
									else
										AblityTrooper1Time.Visible = true
										AblityTrooper1Time.Text = change
									end

								end


								if selectTower.Name ==  "Lieutenant Lv5" then
									if TimeAblity.Value == 0 then
										AblityTrooper2Time.Visible = false
										AblityFrame.AblityTrooper2.TextButton.Visible = true
									else
										AblityTrooper2Time.Visible = true
										AblityTrooper2Time.Text = change
									end

								end
							end
						end)
					end)
					if success then
					else

					end
				end
			end
		end
	end
1 Like

how much times is this function being called? If it is multiple times this could be the issue.

It may happen because of in pairs functions, like it finds 4 children and it will do the function 4 times

hm yeah i should move the button click to another place

it 4 time but with another ablity it 8 times, 24 times

then that is why? I don’t see the function being disconnected so it has 4 different functions calling it.

It is running multiple times because, at the top of the script, you loop through all of the GUI items. In the AbilityFrame.

i moved the button click function already but it still spam like normal

have ablity it spam 8 time or 24 time

sad after i moved the click button function it still like that

after remove the loop it still bug

Did you add a debounce into this script?
If you didn’t, I suggest you add it.

Example:
local debounce = false --- Add a variable.

if debounce == false then --- This will check if the variable is false
debounce = true
wait(2) --- Add how long will it take for debounce to stay true.
debounce = false --- When the wait() is finished, it will set back to false until the debounce is called again.
end

You iterate over the children but are not using your iterator, removing the loop should fix this but I would actually lean into the loop more and reduce your code like so. This should work for all children abilities if they are set up the same way

local function triggedAblity()
	warn("Work")
	-- defined outside the loop because it won't change during the loop
	local TimeAblity = selectTower:FindFirstChild("Time") :: NumberValue
	
	for i, AblityButton in pairs(ui.Selection.UI.AblityFrame:GetChildren()) do
		if AblityButton:IsA("ImageLabel") then
			local AblityFrame = ui.Selection.UI.AblityFrame

			-- using AblityButton iterator to create connection for each item in AblityFrame:GetChildren
			AblityButton.TextButton.MouseButton1Click:Connect(function()
				if TimeAblity.Value == 1  then
					warn("Ablity", AblityButton.Name)
					AblityButton.TextButton.Visible = false
					FuntionAblity:InvokeServer(AblityButton.Name, selectTower)
					wait(0.1)
					AblityButton.TextButton.Visible = true
				end
			end)

			-- pcall around a event connection will never fail, removed it
			TimeAblity.Changed:Connect(function(change)
				if not selectTower then
					return
				end
				
				-- early return, stops the function if names don't match
				if selectTower.Name ~= AblityButton.Name then
					return
				end
				
				-- using boolean operations intead of if statements
				AblityButton.TextButton.Visible = TimeAblity.Value ~= 0
				AblityButton.Time.Visible = TimeAblity.Value ~= 0
				AblityButton.Time.Text = change
			end)
		end
	end
end
1 Like

debounce make more wrost + lag in script

i remove already u can read the chat up there, it still spam

try this if you use triggeredAbility function more than one times

local LastConnections = {}

local function triggedAblity()
	warn("Work")
	for i, LastConnection in ipairs(LastConnections) do
		if LastConnection.Connected then
			LastConnection:Disconnect()
		end

		table.remove(LastConnections, i)
	end

	for i, AblityButton in pairs(ui.Selection.UI.AblityFrame:GetChildren()) do
		if AblityButton:IsA("ImageLabel") then
			if selectTower:FindFirstChild("TimeAblity") then
				local TimeAblity = selectTower:FindFirstChild("TimeAblity")
				local ablityDebounce = false
				local AblityFrame = ui.Selection.UI.AblityFrame

				LastConnections[1] = AblityFrame.AblityTrooper1.TextButton.MouseButton1Click:Connect(function()
					if selectTower.TimeAblity.Value == 1  then
						warn("Ablity")
						AblityFrame.AblityTrooper1.TextButton.Visible = false
						FuntionAblity:InvokeServer("AblityTrooper1", selectTower)
						wait(0.1)
						AblityFrame.AblityTrooper1.TextButton.Visible = true
					end
				end)

				LastConnections[2] = AblityFrame.Oofer.TextButton.MouseButton1Click:Connect(function()
					if selectTower.TimeAblity.Value == 1 then
						ablityDebounce = true
						FuntionAblity:InvokeServer("Oofer", selectTower)
						wait(0.1)
						ablityDebounce = false
					end
				end)

				LastConnections[3] = AblityFrame.AblityTrooper2.TextButton.MouseButton1Click:Connect(function()
					if selectTower.TimeAblity.Value == 1  then
						AblityFrame.AblityTrooper2.TextButton.Visible = false
						FuntionAblity:InvokeServer("AblityTrooper2", selectTower)
						wait(0.1)
						AblityFrame.AblityTrooper2.TextButton.Visible = true
					end
				end)

				LastConnections[4] = AblityFrame.Homeless.TextButton.MouseButton1Click:Connect(function()
					if selectTower.TimeAblity.Value == 1  then
						AblityFrame.Homeless.TextButton.Visible = false
						FuntionAblity:InvokeServer("Homeless", selectTower)
						wait(0.1)
						AblityFrame.Homeless.TextButton.Visible = true
					end
				end)

				local HomelessTime = AblityFrame.Homeless:WaitForChild("Time", 0.1)
				local AblityTrooper1Time = AblityFrame.AblityTrooper1:WaitForChild("Time", 0.1)
				local AblityTrooper2Time = AblityFrame.AblityTrooper2:WaitForChild("Time", 0.1)
				local success, fail = pcall(function()
					LastConnections[5] = TimeAblity.Changed:Connect(function(change)
						if selectTower then
							if selectTower.Name ==  "Homeless" then
								if TimeAblity.Value == 0 then
									HomelessTime.Visible = false
									AblityFrame.Homeless.TextButton.Visible = true
								else
									HomelessTime.Visible = true
									HomelessTime.Text = change
								end

							end


							if selectTower.Name ==  "Lieutenant Lv4" then
								if TimeAblity.Value == 0 then
									AblityTrooper1Time.Visible = false
									AblityFrame.AblityTrooper1.TextButton.Visible = true
								else
									AblityTrooper1Time.Visible = true
									AblityTrooper1Time.Text = change
								end

							end


							if selectTower.Name ==  "Lieutenant Lv5" then
								if TimeAblity.Value == 0 then
									AblityTrooper2Time.Visible = false
									AblityFrame.AblityTrooper2.TextButton.Visible = true
								else
									AblityTrooper2Time.Visible = true
									AblityTrooper2Time.Text = change
								end

							end
						end
					end)
				end)
				if success then
				else

				end
			end
		end
	end
end
1 Like

Did you read the rest of my post? Did you try the script I posted? Was there any difference, because I am confident in this solution for you. I didn’t tell you to remove the loop I said to leverage it and posted a modified version of your script to do so, with comments explaining changes.

1 Like

yes i try it already, i think have a line is bug wait me try fix it

it still spam the unit, but still thank for help