How to detect mouse held?

Hello, after a year and a half without touching a script, I’m starting to learn how to script again.

I’m making a tool and I need to detect if the left mouse button is being held, not if it’s being clicked.

This is the script if you need it:

local mouse = game.Players.LocalPlayer:GetMouse ()
local done = false

mouse.Button1Down:Connect(function()
	if done == false then
		done = true
		script.Parent.shoot:FireServer(mouse.Hit.p)
		wait(0.2)
		done =false
	end
end)

How can I do this? Thank you and sorry if my English is bad.

5 Likes

Since you are using a tool, I’d assume you need it more than just 1 if check, if you are tho, see UIS:IsKeyDown

You will have to bind an action to ContextActionService, with Enum.UserInputType.MouseButton1 and use a boolean to keep track of it. Like this

local bool = false
function(_, State)
    if State == Enum.UserInputState.Change then return end
    bool = (State == Enum.UserInputState.Begin)
end
1 Like

Usually, to detect if the left mouse button is being held down I would use a while loop like so:

local mouse = game.Players.LocalPlayer:GetMouse()
local heldDown = false

mouse.Button1Down:Connect(function()  -- When left mouse button is depressed we make heldDown equal true and loop through a while loop
	heldDown = true
	while heldDown do
		wait()
		print("Left mouse button is being held down")
	end
end)

mouse.Button1Up:Connect(function() -- When left mouse button is released we make heldDown equal false, stopping the loop
	heldDown = false
end)
4 Likes

There are many ways of doing this. I don’t want to overcomplicate stuff, but also don’t want to set a bad example, so here is what I would do:

local userInput = game:GetService("UserInputService") -- We're using the user input service, even if there are other ways to do this
local ticket = 0 -- We're using a ticket system here to make sure that clicks won't be confused with mouse being held
local timeHeld = 0.2 -- In seconds, this would be 200ms, set this to your liking, can also be set to 0
local isHolding = false -- This will be used to avoid firing the leftMouseButtonReleased function without the button being held

-- This code should run once the left mouse button BEGINS being held
function leftMouseButtonHeld()
	isHolding = true
	print("Left mouse button IS BEING held!")
	-- Add your code here
end

-- This code should run once the left mouse button STOPS being held
function leftMouseButtonReleased()
	if not isHolding then return end
	isHolding = false
	print("Left mouse button is NO LONGER being held!")
	-- Add your code here
end

userInput.InputBegan:connect(function(input, gameProcessed)
	if gameProcessed then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		ticket = ticket + 1 -- Increase the ticket count, so that we can track if the user has actually held the mouse button or not
		local currentTicket = ticket -- Stores the CURRENT ticket value. If the user stops holding the mouse button, this will change and fail the if check
		
		if timeHeld > 0 then
			delay(timeHeld, function()
				if ticket == currentTicket then
					leftMouseButtonHeld()
				end
			end)
		else
			leftMouseButtonHeld()
		end
	end
end)

userInput.InputEnded:connect(function(input, gameProcessed)
	if gameProcessed then return end

	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		ticket = ticket + 1		
		leftMouseButtonReleased()
	end
end)
21 Likes

Thank you everyone for the solutions! It helped a lot. :grinning:

1 Like

Sorry to necro, I’m very confused as to what gameProcessed is doing in this situation though and why it needs to be implemented. I’m able to understand everything else in the code and feel comfortable applying a similar method to this to my script, however gameProcessed confuses me greatly and I want to fully understand it before I just add it into my script. Would it not be ending the function immediately? Is it a built-in function or command that I’m not aware of? I see it mentioned no where else in the script, only as parameters for these functions. Is it maybe saying to only run the function once? Though, if that is the case I am lost as to how it is conveying that information. Is it some sort of fail safe, or acting as a debounce? While its not neccessary at all, if anyone has answers to these questions, or is just generally able to explain the purpose of gameProcessed it would be greatly appreciated!

Edit* After more reading I am also confused as for the purpose of:

if timeHeld > 0 then
			delay(timeHeld, function()
				if ticket == currentTicket then
					leftMouseButtonHeld()
				end
			end)
		else
			leftMouseButtonHeld()
        end

Would this not always be true? And even if it wasn’t, whats the purpose of calling the same function regardless of if the first statement is true or not? timeHeld is defined way earlier in the script, and there seems to be no section that is changing its value. Thusfore 0.2 (timeHeld’s value) will always be > than 0 no? Why even have the if statement here? Not asking out of malice or in a condescending tone, just generally curious and confused :slightly_smiling_face:

gameProcessed is a boolean, which described whether some other part of the game has already made use of the input, such as if the user was clicking on a button.


It seems like timeHeld is a configuration thing, so that the user of the script is able to modify it. If the user wants to disable the hold requirement, then they can set it to 0, which instantly fires the leftMouseButtonHeld thing. Otherwise, it will go to the other part of the if statement, and require that the mouse is held for a duration of time.

1 Like