Event Runs Multiple Times

My event runs multiple times and I want it to run only once. I have thought it is because of the “for loop” but I don’t know how to modify the script.

local UserInputService = game:GetService("UserInputService")
local done = false
local plr = game.Players.LocalPlayer
local leftplayers = {}
local debounce = true


script.Parent.MouseButton1Up:Connect(function()
	debounce = true
	
	local ToolIcon = script.Parent.Parent.Parent:FindFirstChild("ToolIcon")
local TextureId = ToolIcon.Image
local ToolAmount = script.Parent.Parent.TextBox.Text
	
	if ToolIcon then
		
		
	while wait(0.1)  do
		if debounce == true then
			

		print("hit")
		
			for i, hum in pairs(game.Players:GetPlayers()) do
				
					print(hum.Name)
					if hum.Name == plr.Name then
					else
						local otherPlayer = hum
						if otherPlayer then

							local otherCharacter = hum.Character
							local HumPart = otherCharacter.HumanoidRootPart

							if otherPlayer then
								local userId = otherPlayer.UserId
								local thumbType = Enum.ThumbnailType.HeadShot
								local thumbSize = Enum.ThumbnailSize.Size420x420
								local content, isReady = game.Players:GetUserThumbnailAsync(userId, thumbType, thumbSize)

								if (HumPart.Position - plr.Character.HumanoidRootPart.Position).Magnitude < 10  then
								 if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name) then
										return
								 else
										local GiveTemp = script.Parent.Parent.Parent.GiveTemplate:Clone()
										GiveTemp.Parent = script.Parent.Parent.Parent.GiveFrame
										GiveTemp.Visible = true
										GiveTemp.ImageFrame.ImageButton.Image = content
										GiveTemp.Name = otherPlayer.Name
								 end
								game.Players.PlayerRemoving:Connect(function(player)
									if player.Name == otherPlayer.Name then
										if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name) then
											script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name):Destroy()
										end
									end
								end)
								
								
							if	script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name) then
										script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name).ImageFrame.ImageButton.MouseButton1Click:Connect(function()
											script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name):Destroy()
											local UpToolAmount = tonumber(ToolAmount)
											game.ReplicatedStorage.InventoryEvents.GiveEvent:FireServer(otherPlayer, TextureId, UpToolAmount)
											debounce = false								
										end)
							end

								
                                   


                            wait(3)

								end
							end	
						end
					
				end
				
			end
			else 
				return
		end
	
		
	
	end
	
	end
end)
3 Likes

Try this:

local UserInputService = game:GetService("UserInputService")
local done = false
local plr = game.Players.LocalPlayer
local leftplayers = {}
local debounce = false  -- you haven't used the debounce yet


script.Parent.MouseButton1Up:Connect(function()
	--  debounce = true      if you set it true here then it is NOT a debounce
	if debounce = false then   -- do your script. If it's true then your 3 second debounce is happening
        debounce = true  -- makes the debounce true so the above if check won't let it happen again
    	local ToolIcon = script.Parent.Parent.Parent:FindFirstChild("ToolIcon")
        local TextureId = ToolIcon.Image
        local ToolAmount = script.Parent.Parent.TextBox.Text
	
    	if ToolIcon then
    		while wait(0.1)  do
        		-- if debounce == true then   the debounce is already checked for true above
    			print("hit")		
    			for i, hum in pairs(game.Players:GetPlayers()) do				
    				print(hum.Name)
    				if hum.Name == plr.Name then
    		    	else    --               why the else? just use 'if not hum.Name == plr.name then' above instead
    			    	local otherPlayer = hum
    					if otherPlayer then
    						local otherCharacter = hum.Character
    						local HumPart = otherCharacter.HumanoidRootPart

    						if otherPlayer then
    							local userId = otherPlayer.UserId
    							local thumbType = Enum.ThumbnailType.HeadShot
    							local thumbSize = Enum.ThumbnailSize.Size420x420
    							local content, isReady = game.Players:GetUserThumbnailAsync(userId, thumbType, thumbSize)

				    			if (HumPart.Position - plr.Character.HumanoidRootPart.Position).Magnitude < 10  then
				        			if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name) then
									return
						    	else
									local GiveTemp = script.Parent.Parent.Parent.GiveTemplate:Clone()
									GiveTemp.Parent = script.Parent.Parent.Parent.GiveFrame
									GiveTemp.Visible = true
									GiveTemp.ImageFrame.ImageButton.Image = content
									GiveTemp.Name = otherPlayer.Name
							    end
						     	game.Players.PlayerRemoving:Connect(function(player)
						    		if player.Name == otherPlayer.Name then
						    			if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name) then
											script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name):Destroy()
							    		end
							    	end
							    end)
																
							    if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name) then
						    		script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name).ImageFrame.ImageButton.MouseButton1Click:Connect(function()
							    	script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name):Destroy()
							    	local UpToolAmount = tonumber(ToolAmount)
					    			game.ReplicatedStorage.InventoryEvents.GiveEvent:FireServer(otherPlayer, TextureId, UpToolAmount)						
			    				end)
			    			end
			    		end
			    	end	
			    end					
    		end
		end
        task.wait(3)   -- moved to here to make the debounce work properly
		debounce = false		
	-- else    these 2 lines aren't needed any more for the debounce to work
	-- return
	end
	--  end   this and the next end don't align with anything above	
	--  end
end)
1 Like

Thanks, I will try it later because I am not at home.

1 Like

Ok, just keep in mind I’ve done some other cleanup for the script (your alignment didn’t seem to work here) and I may have accidentally deleted a letter or line while working in these limited text windows.

1 Like

The event still executes multiple times.

1 Like

You can connect an event once using Once instead of Connect.

Disregard, follow a proper debounce pattern.

1 Like

I tried putting the mousebutton1click outside the loop but it doesn’t detect when it is clicked.

local UserInputService = game:GetService("UserInputService")
local done = false
local plr = game.Players.LocalPlayer
local leftplayers = {}
local debounce = true
local otherplayer 
local ToolTexture
local GiveTemplate



script.Parent.MouseButton1Up:Connect(function()
	debounce = true
	
	local ToolIcon = script.Parent.Parent.Parent:FindFirstChild("ToolIcon")
local TextureId = ToolIcon.Image
local ToolAmount = script.Parent.Parent.TextBox.Text
	ToolTexture = ToolIcon.Image
	
	if ToolIcon then
		
		
	while wait(0.1)  do
		if debounce == true then
			

		print("hit")
		
			for i, hum in pairs(game.Players:GetPlayers()) do
				
					print(hum.Name)
					if hum.Name == plr.Name then
					else
						local otherPlayer = hum
						otherplayer = hum
						if otherPlayer then

							local otherCharacter = hum.Character
							local HumPart = otherCharacter.HumanoidRootPart

							if otherPlayer then
								local userId = otherPlayer.UserId
								local thumbType = Enum.ThumbnailType.HeadShot
								local thumbSize = Enum.ThumbnailSize.Size420x420
								local content, isReady = game.Players:GetUserThumbnailAsync(userId, thumbType, thumbSize)

								if (HumPart.Position - plr.Character.HumanoidRootPart.Position).Magnitude < 10  then
								 if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(otherPlayer.Name) then
										return
								 else
										local GiveTemp = script.Parent.Parent.Parent.GiveTemplate:Clone()
										GiveTemp.Parent = script.Parent.Parent.Parent.GiveFrame
										GiveTemp.Visible = true
										GiveTemp.ImageFrame.ImageButton.Image = content
										GiveTemp.Name = otherPlayer.Name
										GiveTemplate = GiveTemp
								 end
								game.Players.PlayerRemoving:Connect(function(player)
									if player.Name == otherPlayer.Name then
										if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name) then
											script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name):Destroy()
										end
									end
								end)
								
                            wait(3)

								end
							end	
						end					
				end
				
			end
			else 
				break
		end
	
		
	
	end
	
	end
end)



GiveTemplate.ImageFrame.ImageButton.MouseButton1Click:Connect(function()
	script.Parent.Parent.Parent.Parent.Parent.ScreenGui.Enabled = true
end)

Why is debounce set to true when the script starts

Actually I want to make it so when the player releases the button then the players which are near the player appear and then they get refreshed every 3 seconds until the button is clicked that’s why.

Here’s what’s happening.

  1. Button is released
  2. Enter a task.wait(0.1) loop
  3. Enter a loop iterating through each player
  4. Connect PlayerRemoving to the player ← no no number 1
  5. task.wait(3)
  6. Do all of that again ← no no number 2

It’s generally very not recommended to connect a script signal inside of a loop, as if not properly handled, it will cause things like this to happen. What you should do instead is make that connection outside of the loop. From what I see, this should work:

game.Players.PlayerRemoving:Connect(function(player)
  if script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name) then
    script.Parent.Parent.Parent.GiveFrame:FindFirstChild(player.Name):Destroy()
  end
end)

Also, your debounce isn’t doing anything. Before you set it to true, you should check whether or not it’s already true and return if so. Like this:

if debounce then return end

I don’t see where you’re setting it back to false either, but maybe that’s intentional.

1 Like

I made it in a seperate script, but in the serverside script when it finishes I use break but it still makes changes to 2 of them.

game.ReplicatedStorage.InventoryEvents.GiveEvent.OnServerEvent:Connect(function(plr,otherplayer,TextureId)
	
	local Tool
	


	for i,v in pairs(plr.Backpack:GetChildren()) do
		
		if v:IsA("Tool") then
			if v.TextureId == TextureId then
				
				Tool = v
				break
				
				
			end
		end
	end

	


	
	

		local NewTool = Tool:Clone()
		NewTool.Parent = otherplayer.Backpack

	
	
	Tool:Destroy()

end)

Assuming the event is only fired once, there’s no reason why that would be happening for multiple tools. The event is being fired more than once by the client. That’s the only thing it can be. Can you show us the code where the event is fired?

script.Parent.ChildAdded:Connect(function(child)
	if child:IsA('Frame') then
		child.ImageFrame.ImageButton.MouseButton1Click:Connect(function()
			if game.Players:FindFirstChild(child.Name) then
			local otherplayer =  child.Name
			local TextureId = child.ImageFrame.ImageButton.TextureId.Value
			game.ReplicatedStorage.InventoryEvents.GiveEvent:FireServer(otherplayer, TextureId)
			child:Destroy()
			end
		end)
	end
end)

Somehow it’s fixed but the tool doesn’t goes to the otherplayer it only gets destroyed

game.ReplicatedStorage.InventoryEvents.GiveEvent.OnServerEvent:Connect(function(plr,otherplayer,TextureId)
	
	local Tool
	


	for i,v in pairs(plr.Backpack:GetChildren()) do
		
		if v:IsA("Tool") then
			if v.TextureId == TextureId then
				
				Tool = v
				break
				
				
			end
		end
	end

	


	
	
repeat wait(0.1)  until Tool
		local NewTool = Tool:Clone()
		NewTool.Parent = otherplayer.Backpack

	
	
	Tool:Destroy()

end)

Now, it destroys one and clones 4.

I used print at the start and yes the event gets executed multiple times. Why does this happen?

Use prints that actually tell you what the variable is before the if checks. Printing a word after an if only tells you if it is working, not why it isn’t.

For example instead of

if x = 3 then
    print("worked")
    -- code
end

try this

print("x equals ", x)
if x = 3 then
    -- code
end

It might tell you that x = nil or x = 2.9999 which lets you know where to look for troubleshooting.

In which part of my script should I try this?

I used this print at the start and it got executed multiple times.

game.ReplicatedStorage.InventoryEvents.GiveEvent.OnServerEvent:Connect(function(plr,otherplayer,TextureId)
	print("event executed")

Well you’re trying to find out why it’s executing twice, so try finding out if the bottom MouseButton1Click is getting called multiple times:

GiveTemplate.ImageFrame.ImageButton.MouseButton1Click:Connect(function()
	script.Parent.Parent.Parent.Parent.Parent.ScreenGui.Enabled = true
end)

Also, you printed your script the second time and didn’t move the debounce like I mentioned the first time. You didn’t copy all of my script because at the beginning you still have debounce = true, which totally negates the debounce.
At the end there’s still a mess of ends and your debounce is still in the wrong spot.

My script may not have worked, but it’s cleaner to read. Are there any red lines under sections of either of our codes that give any possible error warnings when you view it in Studio?