Draggable UI Mispositioned

As the title says, I’ve attempted to logically create a UI specific draggable UI script. UI specific I mean a script that only works for my frame.

As long as the I am holding either Mouse 1 or Mouse 2 buttons Navigation, it counts the difference between the current and the original X and Y vectors of the mouse. Add an additional offset to these two values to center it (according to the ascending Frame) and move it.
But there is a bug, which makes the Frame go down and right decently fast, and the movement doesn’t stop when I release either button I originally pressed.

Here’s my code:


local M = game.Players.LocalPlayer:GetMouse();
local RunService = game:GetService("RunService");

local active = false;
local save = false;
local mX, mY

local Navigation = script.Parent:WaitForChild("Title");
local Frame = script.Parent.Parent;

Navigation.MouseButton1Down:Connect(function() active = true end);
Navigation.MouseButton2Down:Connect(function() active = true end);
Navigation.MouseButton1Up:Connect(function() active = false end);
Navigation.MouseButton2Up:Connect(function() active = false end);

Navigation.MouseLeave:Connect(function() active = false end);

RunService.Stepped:Connect(function()
	if active == true then
		print("activate")
		if save == false then
			mX, mY = M.X, M.Y;
			save = true;
			print("saved")
		end
		local mXd, mYd = M.X - mX, M.Y - mY;
		local result = UDim2.new(0, mXd+32, 0, mYd+211);
		Frame.Position += result;
		return
	elseif active == false then
		print("deactivate")
		save = false;
		mX, mY = 0, 0;
	end
end)

The active variable determines if there is input, and save is used to know if the original X and Y values are put in variables on input. All should reset when I release the mouse button I originally pressed.
All help is appreciated

1 Like

From what you’ve described as the bug, and what I’m reading in your code, I assume that the problem lies in the fact that Frame.Position += result is still being ran, meaning that active is still true for whatever reason. Could it be that return statement at the end?
Additionally, it is recommended to disconnect from the .Stepped event when you’re done, to prevent memory leaks, which may be the cause of this bug.

2 Likes

I would suggest using this module if TestyLike3’s solution doesn’t work out.

2 Likes

How would I disconnect the function? For RunService.Stepped:Disconnect() it throws an error saying it is not a valid member of the event
I mean I’ve seen a solution once long ago, where I put the .Stepped() event into a variable, making :Disconnect() available on it?

1 Like

Yes, that is how you disconnect it.

local stepHandle
stepHandle = RunService.Stepped:Connect(function()
    ...
end)

...
stepHandle:Disconnect() -- You can also put this into the connection,
                        -- since we've declared the variable before assigning it.
1 Like

The bug was indeed due to Frame.Position += result which I fixed.
I’ve realized there is no point in calculating the distance of two mouse position points, soI’ve changed a couple of things.
The only issue is that I can move the Frame now for 2-3 seconds, then it stops moving, even when I click again. Maybe leaving the button breaks the active value, I just don’t know.

Here’s a snippet:

local SteppedEvent
SteppedEvent = RunService.Stepped:Connect(function()
	if active.Value == true then
		if save == false then
			local mX, mY = M.X/M.ViewSizeX, M.Y/M.ViewSizeY;
			local fX, fY = Frame.Position.X.Scale,Frame.Position.Y.Scale
			dX, dY = fX - mX, fY - mY; -- Save the distance for current input
			save = true;
			print("frame:",fX, fY, "mouse:",mX, mY, "distance:", dX, dY)
		end
		Frame.Position = UDim2.new(M.X/M.ViewSizeX + dX, 0, M.Y/M.ViewSizeY + dY, 0);
	end
end)

active.Changed:Connect(function(value)
	print("CHANGED", value)
	if value == false then
		dX, dY = 0, 0;
		save = false;
		SteppedEvent:Disconnect();
	end
end)
1 Like

Do the print statements still work? I also can’t figure out why this is happening, maybe try reproducing it a bunch of times to see if there’s a pattern?

1 Like

Yes, print statements do work.
I’ll get back to you if I found anything.

1 Like

I’ve reconstructed the script and it works fine without needing to disconnect the function. However, the Frame’s position doesn’t update fast enough, I mean the mouse can move away from the UI object’s area where I detect the input. I use RunService.Heartbeat instead of RunService.Stepped

1 Like

I forgot to mention that you should probably use RenderStepped in this case, since you want to update UI every frame to follow the mouse. This means it should also update at higher refresh rates if the player unlocks the 60FPS limit. (I’m sure physics doesn’t update at higher than 60/30FPS)

1 Like

I could somewhat fix it, move for some reason the frame slides on the Y axis whenever I move it. I’ve tried approaching different methods in attempt to fix it, but I’m not a professional and I just have no clue why it is happening. @TestyLike3

After several attempts on different methods, I could make it work without any major issues. I thank you for your help.

1 Like

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