Can someone tell me how to make a ui dragging system without UIDragDetector
I’m worried that UIDragDetector will deprecated be in the future
I also wanna learn to make something a customizable system
Can someone tell me how to make a ui dragging system without UIDragDetector
I’m worried that UIDragDetector will deprecated be in the future
I also wanna learn to make something a customizable system
Depends on what you would like to do with it, but one way is to detect if the player is clicking the UI, if the player is then update the ui’s position accordingly.
No, when the user is dragging a frame, this is for a plug-in
i’ve made something simple a while back, i’ll hide the code just in case you want to make it yourself, anyways i recommend using Tags to detect which ui can be dragged, what you mostly need is the mouse position in the ui when the user pressed on the ui, which you can use in UserInputService.InputChanged to move the ui, make sure to use AbsolutePosition, and to consider the ui object’s AnchorPoint & AbsoluteSize, as well as the Inset the screengui it belongs to has
local Dragging = false
local DragLocation = Vector2.zero
local DraggingUI = nil
local GUI = game.Players.LocalPlayer.PlayerGui
-- /
repeat task.wait() until #GUI:GetDescendants() >= #game.StarterGui:GetDescendants()
for _, SGUI in GUI:GetChildren() do -- the reason why i did this instead of just using CollectionService is so i can easily get the IgnoreGuiInset from the ScreenGUI it belongs to
if not SGUI:IsA('ScreenGui') then continue end
for _, Descendant in pairs(GUI:GetDescendants()) do
if Descendant:IsA('GuiObject') and Descendant:HasTag('Draggable') then
if not Descendant:FindFirstChild('DRAG-HITBOX') then
local hitbox = Instance.new('ImageButton')
hitbox.Name = 'DRAG-HITBOX'
hitbox.BackgroundTransparency = 1
hitbox.ImageTransparency = 1
hitbox.Size = Descendant:GetAttribute('DRAG-HITBOX-SIZE') or UDim2.new(1, 0, 1, 0)
hitbox.ZIndex = 0
hitbox.Parent = Descendant
hitbox.InputBegan:Connect(function(input, gpe)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch and not gpe then
Dragging = true
DraggingUI = Descendant
DragLocation = Vector2.new(input.Position.X, input.Position.Y) - Descendant.AbsolutePosition - (SGUI.IgnoreGuiInset and game:GetService("GuiService"):GetGuiInset() or Vector2.zero)
end
end)
end
end
end
end
game.UserInputService.InputChanged:Connect(function(input, gpe)
if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch and not gpe then
if Dragging and DraggingUI then
local position = Vector2.new(input.Position.X, input.Position.Y) - DragLocation + (DraggingUI.AbsoluteSize * DraggingUI.AnchorPoint)
DraggingUI.Position = UDim2.new(0, position.X, 0, position.Y)
end
end
end)
game.UserInputService.TouchMoved:Connect(function(input)
if Dragging and DraggingUI then
local position = Vector2.new(input.Position.X, input.Position.Y) - DragLocation + (DraggingUI.AbsoluteSize * DraggingUI.AnchorPoint)
DraggingUI.Position = UDim2.new(0, position.X, 0, position.Y)
end
end)
game.UserInputService.TouchEnded:Connect(function(input)
Dragging = false
DraggingUI = nil
end)
game.UserInputService.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
Dragging = false
DraggingUI = nil
end
end)```
I’m sorry, to ask you this
But can you give me explanation of InputChanged
What is the difference between AbsoluteSize and AbosolutePosition, then the regular size and position?
InputChanged → https://create.roblox.com/docs/reference/engine/classes/UserInputService#InputChanged
it is used mainly to detect of the player moved their mouse / finger and gives us an input object which we can extract the positions from
Size & Position give us the position & size relative TO the parent of the ui object, so if i put a frame of the position 0, 0 in another tiny frame that i moved somewhere in the bottom, that frame is still going to have the position 0, 0 but in reality it’s at the bottom of the screen too, so AbsolutePosition tells us exactly where it is, same applies to AbsoluteSize
For a plugin (or any custom drag), you don’t need UIDragDetector. The usual loop is: capture offset on press → move on InputChanged → clear on release.
Position / Size — relative to the parent (UDim2 scale+offset).AbsolutePosition / AbsoluteSize — screen-space pixels right now (after layouts, scales, insets).Dragging wants screen pixels, then you write back a UDim2 the parent understands.
InputChangedFires while an input is active and its values change (mouse move / finger move). That’s your drag tick. Pair it with InputBegan / InputEnded (or InputBegan on a hitbox + UserInputService.InputEnded).
local UserInputService = game:GetService("UserInputService")
local GuiService = game:GetService("GuiService")
local function makeDraggable(guiObject: GuiObject, screenGui: ScreenGui)
local dragging = false
local grabOffset = Vector2.zero -- cursor relative to object top-left
local function inset(): Vector2
return if screenGui.IgnoreGuiInset then Vector2.zero else GuiService:GetGuiInset()
end
guiObject.InputBegan:Connect(function(input)
if input.UserInputType ~= Enum.UserInputType.MouseButton1
and input.UserInputType ~= Enum.UserInputType.Touch then
return
end
dragging = true
local cursor = Vector2.new(input.Position.X, input.Position.Y)
grabOffset = cursor - guiObject.AbsolutePosition - inset()
end)
UserInputService.InputChanged:Connect(function(input)
if not dragging then return end
if input.UserInputType ~= Enum.UserInputType.MouseMovement
and input.UserInputType ~= Enum.UserInputType.Touch then
return
end
local cursor = Vector2.new(input.Position.X, input.Position.Y) - inset()
local topLeft = cursor - grabOffset
-- honor AnchorPoint so the object doesn’t jump
local size = guiObject.AbsoluteSize
local ap = guiObject.AnchorPoint
local parent = guiObject.Parent
if not parent or not parent:IsA("GuiObject") and not parent:IsA("LayerCollector") then
return
end
-- parent-relative pixel position of the anchor point
local parentAbs = if parent:IsA("GuiObject") then parent.AbsolutePosition else Vector2.zero
local parentInset = if parent:IsA("ScreenGui") then inset() else Vector2.zero
local desiredAnchorScreen = topLeft + size * ap
local rel = desiredAnchorScreen - (parentAbs + parentInset)
guiObject.Position = UDim2.fromOffset(rel.X, rel.Y)
end)
UserInputService.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
or input.UserInputType == Enum.UserInputType.Touch then
dragging = false
end
end)
end
AbsoluteSizemath.floor(x / step) * step)DockWidgetPluginGui / widget mouse APIs if you’re inside a widget rather than PlayerGuiUIDragDetector is fine for many experiences; a hand-rolled drag like this is still the right learning path when you want full control (plugins, custom snap, multi-select).
userinputservice and math
the script depends on how your ui is set up because you need to account for different element sizes
input changed is when any physical input device moves, such as mouse
absolutesize and absoluteposition give you the pixel offset size and position instead of the relative scale value
local selector = {}
local guiObjectPosition
local mousePosition
local isDragging = false
function selector.drag(guiObject: GuiObject, screenGui: ScreenGui)
local UserInputService = game:GetService('UserInputService')
UserInputService.InputBegan:Connect(function(input, isTyping)
if isTyping then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 then
isDragging = true
mousePosition = Vector2.new(input.Position.X, input.Position.Y)
guiObjectPosition = Vector2.new(guiObject.AbsolutePosition.X, guiObject.AbsolutePosition.Y)
end
end)
UserInputService.InputEnded:Connect(function(input, isTyping)
if isTyping then return end
isDragging = false
end)
UserInputService.InputChanged:Connect(function(input, isTyping)
if isTyping then return end
if isDragging == true then
local NewPosition = guiObjectPosition + ((Vector2.new(input.Position.X, input.Position.Y) - mousePosition))
guiObject.Position = UDim2.fromOffset(NewPosition.X,NewPosition.Y)
end
end)
end
return selector
See the problem I have with this script, when i hold left click and move the mouse, it drags the UI even when I’m not touching the ui
he used llm for that Reply btw
Can you please elaborate on that I’m confused what do you mean by llm?
large language model (Ai Slop)
You can use UserInputService and calculate the mouse/touch offset when the player starts dragging, then update the UI position based on the input’s movement. Hope this helps!
I mean… they came out 2 years ago, the odds that they randomly deprecate it anytime in the near future is very slim
But it’s still better to learn how to do things by yourself
all ui elements have a second event for when the mouse enters or leaves it
personally if I were to use this I would add a second layer of checking to see if another variable controlled by this is true before setting dragging to true
alternatively you could use absolute position and size combined with mouse position
this is probably the best method since you can get a boolean directly out of it
he means chatgpt or gemini or claude or something
I knew what they meant by large language model, but thanks for the help