Why mouse.Button1Up:Wait() don't work?

Hello! Can someone please help me and say, why mouse.Button1Up:Wait() don’t stop waiting?
mouse is game:GetService("Players").LocalPlayer:GetMouse()

while true do
	print("Active")
	Scroller.MouseButton1Down:Wait()
	print("MouseIsDown")
	local Offset = mouse.X - Scroller.AbsolutePosition.X - (Scroller.AbsoluteSize.X / 2) + ScrollerBar.AbsolutePosition.X
	local Connection = mouse.Move:Connect(function()
		print("MouseMoved")
		local PosX = mouse.X
		Scroller.Position = UDim2.new(math.clamp((PosX - Offset) / ScrollerBar.Size.X.Offset, 0, 1), 0, 0.5, 0)
		Text.Text = if math.clamp((PosX - Offset) / ScrollerBar.Size.X.Offset, 0, 1) == 0 and Values[1] == "Dis." then "Dis." else tostring(math.round(math.clamp((PosX - Offset) / ScrollerBar.Size.X.Offset, 0, 1) * (Values[2] - (if Values[1] == "Dis." then 0 else Values[1]))) + 1)
	end)
	mouse.Button1Up:Wait() -- The problem
	print("MouseReleased")
	Connection:Disconnect()
end
1 Like

try putting a print() inside the :Wait()

Now, it prints “MouseUp” when Scroller.MouseButton1Down finishes waiting…
mouse.Button1Up:Wait(print("MouseUp"))
image

Change the wait to :Connect(function() then put a task.wait and put print(“Mouse Released”)

The problem is that player can click this scroller button many times, and every click it will create 1 unneeded function, which will lag player.
Also, if I change mouse.Button1Up:Wait() to Scroller.MouseButton1Up:Wait() all works perfectly with connections, but not so perfect when mouse leaves button.

You should just use a Changed Connect event with a debounce to avoid the lag. You could do a seperate function with a spawned task, if you prefer that as well.

It sounds like you’re only wanting to change something when the player is dragging a button. To achieve this, I would suggest that you connect to events rather than use a loop with :Wait()s for events. I say this because the behavior of the events is more reliable in this format. You can achieve this with the following:

local button = script.Parent

local isPressingButton = false
button.InputBegan:Connect(function()
	isPressingButton = true
end)

button.InputEnded:Connect(function()
	isPressingButton = false
end)

local userInputService = game:GetService("UserInputService")

userInputService.InputChanged:Connect(function(inputObject)
	if inputObject.UserInputType==Enum.UserInputType.MouseMovement and isPressingButton then
		--inputObject.Position is the mouse's current position!
		print("Dragging! ", inputObject.Position)
	end
end)

I’m using InputBegan and InputEnded because they’re more reliable than the MouseButton1Down and MouseButton1Up events. I’m using UserInputService.InputChanged to detect when the mouse moves when the player has one of their mouse buttons down. If I used GuiObject.InputChanged, it wouldn’t fire when the mouse leaves the button, which is something I don’t think you want.

Yes, with the code above you can drag with any of the mouse buttons, including the scroll wheel button. If you don’t want that, then you can do this for both the InputBegan and InputEnded parts:

button.InputBegan:Connect(function(inputObject)
	if inputObject.UserInputType==Enum.UserInputType.MouseButton1 then
		isPressingButton = true
	end
end)

button.InputEnded:Connect(function(inputObject)
	if inputObject.UserInputType==Enum.UserInputType.MouseButton1 then
		isPressingButton = false
	end
end)
1 Like

I tried something like this, but I mean connecting 100 functions that triggers every mouse movement isn’t optional. Also you guessed what I want achieve.

BUT:

But my question consist of WHY mouse.Button1Up:Wait() don’t work, but Scroller.MouseButton1Up:Wait() works fine? (Scroller = TextButton)

There’s two scenarios that I can think of that would cause a problem with relying on Button1Up. One pontential scenario is that Button1Up fires before you :Wait() for it. The other scenario is that it simply isn’t firing considering that the Mouse object has been superseded by UserInputService (which is what my snippet uses).

I wouldn’t call my snippet not optimal considering it’s not running the functions constantly. The only one that is running when it doesn’t need to be is the UserInputService.InputChanged event’s function. If you really want it not always listening to that event, then you do something like this:

local button = script.Parent

local mouseInputConnection = nil
button.InputBegan:Connect(function(inputObject)
	if inputObject.UserInputType~=Enum.UserInputType.MouseButton1 then
		return
	end
	
	if mouseInputConnection==nil then
		local userInputService = game:GetService("UserInputService")
		mouseInputConnection = userInputService.InputChanged:Connect(function(inputObject)
			if inputObject.UserInputType==Enum.UserInputType.MouseMovement then
				--inputObject.Position is the mouse's current position!
				print("Dragging! ", inputObject.Position)
			end
		end)
	end
end)

button.InputEnded:Connect(function(inputObject)
	if inputObject.UserInputType~=Enum.UserInputType.MouseButton1 then
		return
	end
	
	if mouseInputConnection then
		mouseInputConnection:Disconnect()
		mouseInputConnection = nil
	end
end)

This type of pattern is extremely common and probably the recommended pattern to use for stuff like this. I have never seen anyone use a while-loop for something like this, nor would I recommend doing something like that for what you’re trying to do.

Edit:

I should probably mention this, but if you want the snippet above to work with touch enabled devices, you’ll need to add another part to the if statement like:

or inputObject.UserInputType~=Enum.UserInputType.Touch

Not only that, but you might need to use UserInputService:GetMouseLocation() in a RunService.Hearbeat event instead of using UserInputService.InputChanged.

1 Like