Functions firing multiple times when they are not supposed to

Sorry new to devforum so this might be all over the place

I’ve had this issue quite often and is usually a put off for many of my games but there’s never any posts about it on devforum.

I’m trying to make a game mechanic where you can print little pieces of paper with a text on them etc. by making new blocks with instance.new. (it works by giving the player a little gui to input the text and from there they can press enter to print said text from the printer).

The printer works totally fine on the first go and when the text is input a block with text is output, but after the first use different amounts of paper start coming out of the printer simultaneously instead of just the one (increasing each time something is printed).

I think the root of the problem stems from the printer being run server-side and the gui having to be run client-side. I’ll leave screen recordings and code below, there’s no issues in the output.

Server script vvv

local debounce = false

-- to make sure it cant be clicked multiple times ^^^

script.Parent.MouseClick:Connect(function(plr)
	if not debounce then
		debounce = true
		local printGui = script.Parent.PrintGui:Clone()
-- there's a gui in the script that gets put into the player vvv
		printGui.Parent = plr.PlayerGui
		game.ReplicatedStorage.PrinterOutcome.OnServerEvent:Connect(function(player, outcome, printText)
-- the printer outcome is for the communication between the server script and client. The outcome itself is to detect if the GUI is closed or a text is entered, and the text is the text from the textbox. ^^^
			if plr == player then
				if outcome == 'print' then
					if printText ~= 'Type Here' then
-- 'type here' is the default text ^^^
						script.Parent.Parent.printer:Play()
-- sound ^^^
						wait(script.Parent.Parent.printer.TimeLength)
-- making the paper vvv
						local paper = Instance.new("Part")
						local surfGui = script.SurfaceGui:Clone()
						local text = Instance.new("TextLabel")
--the drag detector and surface gui had really complex properties that i wasnt bothered to code so i just put them in the script to clone
						local dragDetector = script.DragDetector:Clone()
						dragDetector.Parent = paper
						surfGui.Parent = paper
						text.Parent = surfGui
						text.Size = UDim2.new(1, 0, 1, 0)
						text.TextScaled = true
						text.Text = printText
						paper.Size = Vector3.new(1.956, 0.13, 1.175)
						paper.Parent = workspace
						paper.Anchored = true
-- to spawn the paper in the printer vvv
						paper.CFrame = script.Parent.Parent.Parent.SpawnPart.CFrame
						paper.Anchored = false
						paper.Name = 'PrintPaper'
						script.Parent.Parent.paper:Play()
--paper sound ^^^
						wait(2)
						debounce = false
-- to make sure the function can't be spammed ^^^
                        return
					end
				elseif outcome == 'close' then
-- wasn't too sure what to do here but it worked
					wait(2)
					debounce = false
					return
				end
			end
		end)
	end
end)

Local script vvv

local uis = game:GetService("UserInputService")
local plr = game.Players.LocalPlayer

-- for when the text is entered and sent to the printer
uis.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.Keyboard then
		if input.KeyCode == Enum.KeyCode.Return then
-- deciding outcome vvv
			local outcome = 'print'
			game.ReplicatedStorage.PrinterOutcome:FireServer(outcome, script.Parent.TextBox.Text)
-- destroying the gui so it goes off the screen vv
			script.Parent.Parent:Destroy()
		end
	end
end)

script.Parent.Close.MouseButton1Click:Connect(function()
-- there's an X button on the screen that allows the player to close the tab
	local outcome = 'close'
	game.ReplicatedStorage.PrinterOutcome:FireServer(outcome, script.Parent.TextBox.Text)
	script.Parent.Parent:Destroy()
-- sends the outcome to the server script etc.
end)

I’m really grateful with any response to this post as it’s an issue I’ve been having for quite some time. I’m not sure if it’s a problem with how I’ve been doing it but I would really appreciate any help.

File upload wasn’t working so here’s a link to the screen recording:

**There’s delay because there’s a sound that you probably wont be able to hear on the video but it plays in the game.

Really long post but I’d really appreciate some help.

game.ReplicatedStorage.PrinterOutcome.OnServerEvent:Connect(function(player, outcome, printText)

This is the source of your problems. Every time the player clicks, you are creating a connection.
A connection is essentially going to run whenever a certain condition is met. Multiple connections can exist for the same piece of information, and connections typically must be disconnected later.

When you do not disconnect, you have a memory leak. Every time I click here, it will create another connection, and will run when the printer is enabled. This means I could tell the server to expect 80 prints, and even if only one is ran through, all 80 will activate because they require the same conditions to be true.

What you must do is simple.

local connection
connection = game.ReplicatedStorage.PrinterOutcome.OnServerEvent:Connect(function(player, outcome, printText)
-- the printer outcome is for the communication between the server script and client. The outcome itself is to detect if the GUI is closed or a text is entered, and the text is the text from the textbox. ^^^
			if plr == player then
				if outcome == 'print' then
					if printText ~= 'Type Here' then
-- 'type here' is the default text ^^^
						script.Parent.Parent.printer:Play()
-- sound ^^^
						wait(script.Parent.Parent.printer.TimeLength)
-- making the paper vvv
						local paper = Instance.new("Part")
						local surfGui = script.SurfaceGui:Clone()
						local text = Instance.new("TextLabel")
--the drag detector and surface gui had really complex properties that i wasnt bothered to code so i just put them in the script to clone
						local dragDetector = script.DragDetector:Clone()
						dragDetector.Parent = paper
						surfGui.Parent = paper
						text.Parent = surfGui
						text.Size = UDim2.new(1, 0, 1, 0)
						text.TextScaled = true
						text.Text = printText
						paper.Size = Vector3.new(1.956, 0.13, 1.175)
						paper.Parent = workspace
						paper.Anchored = true
-- to spawn the paper in the printer vvv
						paper.CFrame = script.Parent.Parent.Parent.SpawnPart.CFrame
						paper.Anchored = false
						paper.Name = 'PrintPaper'
						script.Parent.Parent.paper:Play()
--paper sound ^^^
						wait(2)
						debounce = false
-- to make sure the function can't be spammed ^^^
                        return
					end
				elseif outcome == 'close' then
-- wasn't too sure what to do here but it worked
					wait(2)
					debounce = false
					return
				end
			end
                        connection:Disconnect()
		end)

To explain briefly, I created a variable connection to store the connection to the event. Then, it is defined as the connection.
After the connection is ran, it will reach the end “connection:Disconnect()” which will disable this connection and prevent it from running again. Consider it as a stop button of sorts.

No further action is required, but ensure that I properly placed it at the end of the event before the correct end)

OH MY GOD YOU ARE A LIFE SAVER

All this time I thought ‘return’ meant the same thing but this is brilliant thank you so much

Initially when I tried it it didn’t work but I just swapped it out for where i had the 'return’s and it’s totally fine

Thanks so much mate you’re a legend

No problem,

return is used to call the end of a function, it is almost similar to the break call which is used to end a loop. return also returns any value positioned after it at any point before the relevant end, which can then be collected for later use where the function was called from.

Generally, connections will only disconnect under these circumstances:

  • The connection’s source object is destroyed. (nil cannot be connected to)
  • The relevant property is no longer accessible.
  • The connection is manually cancelled.

I recommend you always assume a connection will not disconnect automatically, unless it is clearly one of these circumstances.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.