Getting mouse position on screen while holding mousebutton

This is what I currently got, problem I’m trying to overcome is how to cast ray while the mouse is being held down.

local Holding = false

local function InputBegan(input, GPE)
	if GPE then return end

	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		Holding = true
		
		local IgnoreList = {Character}

		local NewRay = Camera:ScreenPointToRay(input.Position.X, input.Position.Y, 0)
		local Part = workspace:FindPartOnRayWithIgnoreList(Ray.new(NewRay.Origin, NewRay.Direction * 50), IgnoreList)
		
		if not Part then return end
			
		Hit:FireServer(Part)
	end
end

local function InputEnded(input)
	Holding = false
end

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

I thought of doing

while Holding do
		local IgnoreList = {Character}

		local NewRay = Camera:ScreenPointToRay(input.Position.X, input.Position.Y, 0)
		local Part = workspace:FindPartOnRayWithIgnoreList(Ray.new(NewRay.Origin, NewRay.Direction * 50), IgnoreList)
		
		if not Part then return end
			
		Hit:FireServer(Part)
    wait()
end

But input wouldn’t be valid

Keep the connection you have, create a variable for the mouse position outside of the functions so its global to the functions. And use create another function thats connected to mouse with the move event; Mouse.Move:connect(). Use that function to change your variable.

UserInputService:IsMouseButtonPressed(UserInputType mouse_button_type) is a thing. It determines whether or not the mouse button enum given is pressed.

Not sure if I’m using it right, but doesn’t work

while UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
	print('Yes')
	
	wait()
end

That is how you use it, but you would still need it to be nested in an InputBegan event listener or something.

Hmm ok, so guessing I don’t need to listen for InputEnded then??

You would not need to listen for it, correct.

How can I get when the mouse has stopped being held?

local function InputBegan(input, GPE)
	if GPE then return end
	
	while UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
		local NewRay = Camera:ScreenPointToRay(input.Position.X, input.Position.Y, 0)
		local Part = workspace:FindPartOnRayWithWhitelist(Ray.new(NewRay.Origin, NewRay.Direction * 20), MaterialSources)
		
		if not Part then return end
			
		Hit:FireServer(Part)
		
		wait()
	end
	
	print('Done')
end

Would prints Done after every input

Because if the input is something else, :IsMouseButtonPressed would return false, so just nest it in an if clause:

if input.UserInputType == Enum.UserInputType.MouseButton1 then
    while UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
        -- Do something!
    end
    print("Done holding the mouse")
end
local function InputBegan(input, GPE)
	if GPE then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		print(1)
		while UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
			print(2)
			local NewRay = Camera:ScreenPointToRay(input.Position.X, input.Position.Y, 0)
			local Part = workspace:FindPartOnRayWithWhitelist(Ray.new(NewRay.Origin, NewRay.Direction * 20), MaterialSources:GetChildren())
			
			if not Part then return end
				
			Hit:FireServer(Part)
			
			wait()
		end
		
		print('Done')
	end
end

Prints 1 and 2, but never Done

Because the mouse button 1 is never released

If I click and release it does not print Done I can spam click, and all I get in the output is
1
2
1
2
1
2
1
2

I think a dynamic connection would be best while using InputChanged, like this

local Holding = false
local firingConnection=nil


local function firing(input, GPE)
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		local IgnoreList = {Character}
	
		local NewRay = Camera:ScreenPointToRay(input.Position.X, input.Position.Y, 0)
		local Part = workspace:FindPartOnRayWithIgnoreList(Ray.new(NewRay.Origin, NewRay.Direction * 50), IgnoreList)
		
		if not Part then return end
			
		Hit:FireServer(Part)
	end
end

local function InputBegan(input, GPE)
	if GPE then return end

	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		Holding = true
		firingConnection = UserInputService.InputChanged:Connect(firing)
	end
end

local function InputEnded(input)
	if input.UserInputType==Enum.UserInputType.MouseButton1 then
		Holding = false
		if firingConnection then
			firingConnection:Disconnect()
			firingConnection=nil
		end
	end
end

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

Okay, then what you could try is adding another condition to your guard:

if GPE or input.UserInputType ~= Enum.UserInputType.MouseButton1 then
    return
end

And then you can just remove the if clause that checks if the input type was equal to the left mouse button.

Still same problem. Only prints 1 and 2

Is this the code more or less?

local function InputBegan(input, GPE)
	if GPE or input.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
	
	print(1)
	while UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
		print(2)
		local NewRay = Camera:ScreenPointToRay(input.Position.X, input.Position.Y, 0)
		local Part = workspace:FindPartOnRayWithWhitelist(Ray.new(NewRay.Origin, NewRay.Direction * 20), MaterialSources:GetChildren())
			
		if not Part then return end
				
		Hit:FireServer(Part)
			
		wait()
	end
		
	print('Done')
end

That’s the exact code yes
30 characters

I fixed it, problem was here

if not Part then return end

to

if Part then
-- Do stuff
end
1 Like

We completely overlooked it didn’t we. I would recommend printing after the ray cast as well so this won’t happen again.

Movement of the mouse fires InputChanged. Use InputBegan and InputEnded respectively to determine when the mouse has been pressed or released and put your mouse movement logic in InputChanged.