Interaction
How to Make a Draggable Roblox GUI
A draggable window, inventory or settings panel feels native. The trick is UserInputService: start dragging on press, move the Frame on InputChanged, and stop on release. The key detail is recording the offset between the cursor and the Frame at the start, so it doesn't snap to the corner.
1. Track press, move and release
Listen on the title bar (not the whole panel) so buttons inside still work. InputBegan starts the drag; UserInputService.InputChanged moves it; InputEnded stops it.
local UserInputService = game:GetService("UserInputService")
local dragging, dragStart, startPos
titleBar.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
or input.UserInputType == Enum.UserInputType.Touch then
dragging = true
dragStart = input.Position
startPos = frame.Position
end
end)2. Move the Frame with the cursor
On InputChanged, add the cursor's travel since dragStart to the Frame's start position. Mixing Scale and Offset in UDim2.new keeps it working regardless of how the Frame was positioned.
UserInputService.InputChanged:Connect(function(input)
if not dragging then return end
if input.UserInputType == Enum.UserInputType.MouseMovement
or input.UserInputType == Enum.UserInputType.Touch then
local delta = input.Position - dragStart
frame.Position = UDim2.new(
startPos.X.Scale, startPos.X.Offset + delta.X,
startPos.Y.Scale, startPos.Y.Offset + delta.Y
)
end
end)
UserInputService.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
or input.UserInputType == Enum.UserInputType.Touch then
dragging = false
end
end)Templates to start from
Roblox Main Menu GUI
A clean centered main menu: game title, primary Play button in Electric Blue, and secondary action buttons — stacked with a UIListLayout so it stays tidy on any screen size.
Roblox Shop GUI
A game shop panel with a header and a ScrollingFrame whose children auto-arrange into a grid via UIGridLayout — drop in as many items as you want and they tile automatically.
Roblox Settings GUI
A settings panel: each option is a row with a label and a toggle pill, stacked vertically with UIListLayout and inner padding from UIPadding.
FAQ
Why does the Frame jump to the cursor when I grab it?
You're setting Position to the cursor directly. Instead, record startPos = frame.Position at drag start and add the cursor's delta to it, so the Frame keeps its grab point.
Does this work on mobile?
Yes — handle Enum.UserInputType.Touch the same way as MouseButton1 in InputBegan and InputEnded, and Touch in InputChanged.
