MouseLeave/MouseEnter have gotten significantly more reliable, but still have some remaining issues we’re working to fix:
- MouseEnter can sometimes fire before MouseLeave on the previous object.
- MouseEnter/MouseLeave fire for all objects under the cursor, instead of the one on top (and this is hard to fix without breaking games).
- Objects can get stuck in hovered state if they were the last hovered element when the mouse leaves the game window.
Currently, implementing your own draggable is a little complicated because of the need to bind to UserInputService, but I’m currently working on a change which will make it so that if you mouse down on a button, it will capture your mouse until you release the mouse button. This makes it very easy to implement sliders, scrollbars, and drag+drop because the only events you need are GuiObject’s
Here’s an old code snippet I wrote when Draggable got deprecated, which you can base your code off of in the mean time. This code should continue working after the changes above are shipped, but you won’t have to write as much code to implement dragging once those changes go live. This snippet uses the same strategy described by @Fm_Trick, but also handles touch input.
local UserInputService = game:GetService("UserInputService")
local gui = script.Parent
local function update(input)
local delta = input.Position - dragStart
gui.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
dragging = true
dragStart = input.Position
startPos = gui.Position
if input.UserInputState == Enum.UserInputState.End then
dragging = false
if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
dragInput = input
if input == dragInput and dragging then