Function Running Too Many Times

Hello, wondering if anyone could help me with this issue I’ve been having on a lot of my scripts:

I have an input ended function inside of a input began function and if the input ended after I clicked the key 10 times, the input ended prints “F has been ended” 10 times, instead of just once. I don’t know of any ways to completely end the entire input began function if the input has already ended, any help would be appreciated.

My script:

local UserInputService = game:GetService("UserInputService")

UserInputService.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.F then
		local Holding = true
		UserInputService.InputEnded:Connect(function(Input)
			if Input.KeyCode == Enum.KeyCode.F then
				Holding = false
				print("F has been ended")
			end
		end)
		print("F has been pressed")
		while Holding do
			wait(1)
			if Holding then
				print("Still holding")
			end
		end
	end
end)

Hey!

So, you may be looking for :Disconnect(). Here is an example of how to use it:

local connection
connection = workspace.ChildAdded:Connect(function(thing)
    if thing.Name == "Stop" then
        connection:Disconnect() -- disconnect the current function! It won't fire again.
    end
end

You could use this to disconnect the InputBegan function, for example, if you only wanted to run it once.

Hope this helps.

1 Like

Worked perfectly and I never knew that was a thing, thanks.

1 Like

(Edit: first method was already explained, but I believe the second method is the best way to go)
Notice how every time F is pressed, you’re creating another connection to check if F is released?

Basically, what happens is every time you let go of F, that function is fired, as well as all the previous ones that were called. You either have to clean this up or separate the events. There’s multiple ways to do this:

  1. Disconnect the event after F is released
UIS.InputBegan:Connect(function(input)
    if input.KeyCode == Enum.KeyCode.F then
        local holding = true
        local connect = nil
        connect = UIS.InputEnded:Connect(function(input2)
            if input2.KeyCode == Enum.KeyCode.F then
                holding = false
                connect:Disconnect()
            end
        end)
        while holding do
            print"Still holding"
            wait(1)
        end
    end
end)    
  1. Separate the events:
local holdingF = false
UIS.InputBegan:Connect(function(input)
    if input.KeyCode == Enum.KeyCode.F then
        holding = true
        while holding do
            wait(1)
        end
    end
end)

UIS.InputEnded:Connect(function(input)
    if input.KeyCode == Enum.KeyCode.F then
        holding = false
    end
end)
3 Likes

Separating the event is a far better idea than connecting it in InputBegan. It’s pointless to include the ended event in the begin event.

You can also use InputChanged to get Begin and Ended states all in one go.

local holding = false

UserInputService.InputChanged:Connect(InputObject, GameProcessedEvent)
    if InputObject.KeyCode == Enum.KeyCode.F then
        holding = (InputObject.UserInputState == Enum.UserInputState.Begin)
        while holding do -- Will not run if holding is false
            wait(1)
        end
    end
end)

holding becomes true only if UserInputState is begin, all other instances make it false. Realistically, you wouldn’t need it to be true for any other UserInputState. I like this version a lot because you only connect one function and handle it right from the parameters there.