Help with detecting if input is held

So I’ve created 2 scripts, one localscript in a folder in startergui and another normal script in a folder in workspace. The local script is supposed to detect a player’s input and use a remote to make the server do something, in this case turn on a function. The issue I’m having is that I need the server to be able to constantly detect if the player is holding the button and if not trigger another function, but I can’t figure out a way to make the server be able to constantly detect if the button is held or not, I’ve tried fixing it multiple times but I can’t.

local script:

UserInputService.InputBegan:Connect(function(Input, keyHeld)
	while true do
		wait(0.1)
		if Db and Input then
			if UserInputService:IsKeyDown(Input.KeyCode) then
				keyHeld = true
				DecorRemote:FireServer(Input.KeyCode, keyHeld)
				Db = false
				wait(0.1)
				Db = true
			else
				keyHeld = false
				DecorRemote:FireServer(Input.KeyCode, keyHeld)
				Db = false
				wait(0.1)
				Db = true
			end
		end
	end
end)

Normal script:

		DecorRemote.OnServerEvent:Connect(function(player, Input, keyHeld)
			while true do
				wait(1)
				if Input then
					print(keyHeld)
                     functionOfChoice()
					else
						functionOfChoiceHere()
					
					end
				end
			end
		end)

(There might look like the spacing is weird or there are extra ends, thats because I had to remove some things in order to not leak the script)

Thank you!

1 Like

What is the “Db” variable? Is it like debounce?

1 Like

I would honestly suggest using an easier example

UserInputService.InputBegan:Connect(function(Input, Processed)
	if Processed then return end
    if Input.KeyCode == Enum.KeyCode.X then
       -- if the key pressed (thats given above) then  do this
    end
end)

I would instead advise to try something like this, and also don’t use while wait() do loop in there and instead do it seperately if the keyHeld value is true then do the necessary things you need.

Also your script doesn’t register because on the event UserInputService.InputBegan it gives 2 arguments (the input, and if it was processed) and you cannot change it within the script.

Alternatively in some cases you can do a loop and check if the key is down.

local keyHeld = false

while task.wait(1) do --// waits every second to check
   if UserInputService:IsKeyDown(Enum.Keycode.X) then
       keyHeld = true
   else
       keyHeld = false
   end
end
1 Like

i suggest making a variable like isHolding on the server, setting that to true upon the remote event firing

then have a while isHolding loop that does what you tell it to do

then on the client, fire a different remote event upon input ending
that different remote event should disable isHolding

note that the isHolding bool should be stored in whatever you’re trying to edit, if it’s a tool, make it in a tool and so on

if you’re not trying to edit something that has an insertable object then uh, idk

1 Like

This is what I would reccomend:


-- Services --

local UserInputService = game:GetService('UserInputService')



-- Variables --

local Key = Enum.KeyCode.X
local HoldDuration = 1

local HoldingTask = nil



-- Functions --

local function Hold (): nil
	task.wait(HoldDuration)
	
	print(('You held the %s key for %i seconds!'):format(Key.Name, HoldDuration))
end


local function OnInputBegan (Input: InputObject): nil
	local KeyCode = Input.KeyCode
	if KeyCode ~= Key then return end
	
	HoldingTask = task.spawn(Hold)
end


local function OnInputEnded (Input: InputObject): nil
	local KeyCode = Input.KeyCode
	if KeyCode ~= Key then return end
	
	if HoldingTask then task.cancel(HoldingTask) end
end



-- Code --

UserInputService.InputBegan:Connect(OnInputBegan)
UserInputService.InputEnded:Connect(OnInputEnded)

Explanation:

Every time the UserInputService detects that an input has started, it checks if the input that started is the same as the key you want to hold. After that it starts a function on a different thread, making it run independently from the other code.

If the UserInputService detects that the user released the desired key, it cancels that thread.

Hopefully this explanation is good enough for you to understand (as I normally don’t explain things haha). If you have any question please ask!

1 Like

So this wouldn’t really work because I need the functions to trigger on the server-side and so I need the server to also check if the right key is being held. Also seperate functions need to trigger if the player stops holding the designated key
Thank you tho

1 Like

To my knowledge, the server can’t check if the player is holding a key, as that gets handled client-wise.

If you want to send a signal to the server whenever the key has been held for x amount of time, or when it is unpressed, you can use remote events!

For example:

-- Services --

local UserInputService = game:GetService('UserInputService')
local ReplicatedStorage = game:GetService('ReplicatedStorage')



-- Variables --

local OpenDoorEvent = ReplicatedStorage.OpenDoorEvent
local CloseDoorEvent = ReplicatedStorage.CloseDoorEvent

local Key = Enum.KeyCode.X
local HoldDuration = 1

local HoldingTask = nil



-- Functions --

local function Hold (): nil
	task.wait(HoldDuration)
	
    -- Send signal to the server to open door after holding key
	OpenDoorEvent:FireServer()
end


local function OnInputBegan (Input: InputObject): nil
	local KeyCode = Input.KeyCode
	if KeyCode ~= Key then return end
	
	HoldingTask = task.spawn(Hold)
end


local function OnInputEnded (Input: InputObject): nil
	local KeyCode = Input.KeyCode
	if KeyCode ~= Key then return end
	
	if HoldingTask then task.cancel(HoldingTask) end

    CloseDoorEvent:FireServer() -- Send signal to the server to close the door
end



-- Code --

UserInputService.InputBegan:Connect(OnInputBegan)
UserInputService.InputEnded:Connect(OnInputEnded)

maybe handle it with boolean and InputEnded event?

UserInputService.InputBegan:Connect(function(k, g)
  if g then return end
  if k.KeyCode == Enum.KeyCode.YOURKEY then
    specialbool = true
  end
end)

UserInputService.InputEnded:Connect(function(k, g)
  if g then return end
  if k.KeyCode == Enum.KeyCode.YOURKEY then
    specialbool = false
  end
end)

-- coroutine to check boolean without yielding script
coroutine.resume(coroutine.create(function()
  while task.wait(1) do
    if specialbool == true then
      -- code
    end
  end
end))

I don’t think this is what OP is going for.

Your script checks every second if the key is being pressed down, resulting in it running the code every second when the key is down and running the code without it being held down for x amount of time.

1 Like

main goal is reached, optimization is not my problem, however i know that this solution is not ideal

1 Like

The main goal is, in fact, not reached. OP asked for a function to run whenever a key is held down for a set amount of time. Using a while loop is not the solution. If you time it right, you can run it the moment you press the key, or wait the entire second. I don’t prefer to gamble for my keypresses.

Anyway, have a nice day.

2 Likes

Yes! That is exactly what I’ve been trying to do, but its really glitchy and not working. You can see my attempt in the original post

By the way, what I meant by check is I tried to make the local script check the key being pressed and then sent that to the server-side

Hopefully my solution works!

All you have to do is in a server script add the OnServerEvent connection and make that open the door.

I would recommend two RemoteEvents, one for opening the door and one for closing it! :slight_smile:

1 Like

Hi, so your solution doesn’t really work sorry
I’ll keep searching for other solutions I suppose

1 Like