Draggable property is hidden on gui objects

As of this morning the Draggable property has been hidden. It still exists, but it’s not longer displayed on the properties window.

Nowhere to be seen. :frowning:

Repro steps:

  1. Open up a new place in studio (or any old one)
  2. Insert a Frame or any Gui object and select it
  3. Check for the Draggable property

I can repro this behavior 10/10 times, as can others I’ve asked to test. I’m on a windows machine.

13 Likes

Same here. Really annoying.

2 Likes

It’s been deprecated.

15 Likes

Oh. Is there any particular reason why? Will there be any alternative method offered?

14 Likes

It’s never worked very well, and it’s not very flexible. You can’t implement behaviors like snapping or constraints using it, and when you decide you need those, your only option is to rewrite it from scratch. The concept of clicking and dragging is also foreign for gamepad controls, so relying on them in your UX is kind of bad.

Here’s a snippet which actually works better than the Draggable property ever did.

local UserInputService = game:GetService("UserInputService")

local gui = script.Parent

local dragging
local dragInput
local dragStart
local startPos

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)
end

gui.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		dragging = true
		dragStart = input.Position
		startPos = gui.Position
		
		input.Changed:Connect(function()
			if input.UserInputState == Enum.UserInputState.End then
				dragging = false
			end
		end)
	end
end)

gui.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
		dragInput = input
	end
end)

UserInputService.InputChanged:Connect(function(input)
	if input == dragInput and dragging then
		update(input)
	end
end)

Update (September 2024)

140 Likes

Why can’t that just he the default behavior then?

37 Likes

We understand the technical reasoning behind the depreciation, but why was it made so suddenly and without warning? I don’t recall Roblox making a public announcement (if they have yet to do so after the fact) or making a poll asking developers if they still needed the property. I recently implemented draggable UI elements in my game so now I can’t even access the Draggable property to switch it off without a script or replacing the dozens of elements entirely. The dragging behavior has always worked just fine for me, and snapping/constraining is not too difficult. This change is very frustrating, and I don’t understand how it was so critical that it had to be removed at all.

15 Likes

Ugh. I get the reason why this was being deprecated but I have a legacy game to support until a new version is pushed out- its terrible UX relies on dragging. I really wish I had a notice; there was a small spike in dislikes and nobody told me it wasn’t working until today.

3 Likes

The property should still be working, it is just deprecated.

5 Likes

Could’ve sworn it wasn’t working where it was being used- works now though.

2 Likes

I do recall a post just before Draggable was deprecated notifying developers about it. Regardless, you can still set the property whether it’s in the properties panel or not, and it will work just as it worked before, so it doesn’t really matter.
(sorry for the late reply, just wanted to clear it up)

1 Like

There is no reason why it was deprecated other than that it “never worked very well”, and on top of that, I don’t see why it was never fixed. For new players that want to drag GUIs around, they now are required to incorporate code in a place that previously, was not required.

It should be fixed and re implemented, because it is a feature that in my experience has been used widely in many games, particularly for novice developers.

I have successfully been able to implement constraints and snapping in combination with instances that have Draggable enabled.

17 Likes

I second this. Implementing dragging I’ve found to be pretty simple (I’ll take a spelling check because I haven’t looked at the wiki, but if you remember if it’s -ed or -ing off the top of your head, good for you):

local Frame
local DragConnection 

local function Drag()
    -- constrain position to acceptable ranges
    local P = UDim2.new(0,math.max(MinXPosition,math.min(MaxXPosition,Frame.Position.X.Offset)),0,math.max(MinXPosition,math.min(MaxYPosition,Frame.Position.Y.Offset))
    -- apply position to Frame
    Frame.Position = P
    FrameJustGotDragged(P.Position.X.Offset-MinXPosition,P.Position.Y.Offset-MinYPosition) -- send the new input to wherever it's needed
end

local function DragBegin()
    DragConnection = Frame.Changed:connect(Drag)
end

local function DragEnded()
    if DragConnection then
        DragConnection:disconnect()
    end
end

Frame.DragBegin:connect(DragBegin)
Frame.DragEnded:connect(DragEnded)

This is simpler for sliders because one component is hard-coded, either the X component for vertical sliders or the Y component for horizontal sliders.

EDIT:

Here is a code block from an actual project:

	ReverserHandleDragger.DragBegin:connect(function()
		local dragged = ReverserHandleDragger.Changed:connect(function() -- anonymous function to constrain frame, calculate input, and pass it on up
			if not ReverserLocked then
				local px = ReverserHandleDragger.Position.X.Offset -- this is a horizontal slider
				if px > 40 then -- over the max
					px = 40 -- set px to max
					ReverserHandleDragger.Position = UDim2.new(0,px,0,0)
				elseif px < -10 then -- under the min
					px = -10 -- set px to min
					ReverserHandleDragger.Position = UDim2.new(0,px,0,0)
				elseif ReverserHandleDragger.Position.Y.Offset ~= 0 then
					ReverserHandleDragger.Position = UDim2.new(0,px,0,0) -- I probably could have moved this line out of the if block but whatever
				end
				local intermidiatesetting = (px-15)/25 -- alpha from -1 to 1
				if intermidiatesetting < -.333 then
					ReverserSetting =-1 -- put the train in reverse
					ThrottleLocked = false -- unlock the throttle
				elseif intermidiatesetting > .333 then
					ReverserSetting = 1 -- put the train in forward
					ThrottleLocked = false -- unlock the throttle
				else
					ReverserSetting = 0 -- put the train in neutral
					ThrottleLocked = true -- lock the throttle
				end
				if ReverserSetting ~= PreviousReverserSetting then
					remote:FireServer({["Reverser"]=ReverserSetting}) -- tell the server what we are doing
				end
				PreviousReverserSetting = ReverserSetting -- look for changes in the future
				ConfigureReverserHandle() -- update the GUI
			else
				ReverserHandleDragger.Position = UDim2.new(0,ReverserSetting*25+15,0,0) -- locked in place
			end
		end)
		local dragstop = nil
		dragstop = ReverserHandleDragger.DragStopped:connect(function() -- clean up after yourself
			ForceReverserHandle()
			dragged:disconnect()
			dragstop:disconnect()
		end)
	end)

As far as snapping, CmdUtl 5.0.0 has this, and I’m pretty sure SBS has it too. I’ve done it as well, but I’m not about to go deep diving to find it.

I’m missing why “snapping or constraints cannot be implemented” and am still questioning why it was deprecated. I have never had any outstanding issues with it.

5 Likes

I’m so confused why the solution to “hey draggable doesn’t work that well” is to nuke the feature instead of changing it work properly.

Should we just nuke every feature that developers can potentially do better in lua?

113 Likes

2 posts were merged into an existing topic: Off-Topic Posts

Please only bump bug reports to add significant information related to the issue

Draggable officially stopped working, or at least for me because I enabled the property and it doesn’t does anything. RIP.

1 Like

Hey, sorry to bump an old post, but this doesn’t work on mobile (camera moves alongside the dragged guis).

Here’s a fix, I thought that I should post here rather than making a new post (unfortunately, I couldn’t find any direct way to stop the camera via contextservice or userinputservice, but if theres a way to just temporarily stop the camera’s binding, that’d be better than this)

local UserInputService = game:GetService("UserInputService")

local gui = script.Parent

local dragging
local dragInput
local dragStart
local startPos

local gameProc

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)
end

gui.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		dragging = true
		dragStart = input.Position
		startPos = gui.Position

		input.Changed:Connect(function()
			if input.UserInputState == Enum.UserInputState.End then
				dragging = false
			end
		end)
	end
end)

gui.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
		dragInput = input
	end
end)

UserInputService.InputChanged:Connect(function(input,gameprocessed)
	if gameprocessed then
		gameProc=gameprocessed
	end
	if input == dragInput and dragging then
		update(input)
	end
end)

-- stop the camera when moving guis --
local cam=workspace.CurrentCamera
local lastcamcframe
local moving

-- character stuff so moving doesn't make camera lock
local lp=game:GetService("Players").LocalPlayer
local hum=lp.Character:FindFirstChildOfClass("Humanoid")
repeat hum=lp.Character:FindFirstChildOfClass("Humanoid") wait() until hum --Shouldn't wait that long

workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):connect(function()
	if dragging then
		if not lastcamcframe then
			lastcamcframe=cam.CFrame
		end
		if hum.MoveDirection.Magnitude<.5 then
			cam.CFrame=lastcamcframe
		end
		return
	end
	lastcamcframe=cam.CFrame
end)

I agree with other people in this thread. Please add back draggable. The code to make it work is either available or close to available, and it doesn’t seem that hard to make in comparison to other quality of life improvements you guys have made.

10 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.