Changing frame position in UIGridLayout

Hello all, currently I am working to implement a drag and drop inventory system for my game. [See screenshot]

Marked in red I have a UIGridLayout in ScrollingFrame. Inside the grid I have smaller frames representing items. I frame has a InputBegan function so it’s possible to move it with mouse drag. (The upper 5 frames aren’t in grid and aren’t relevant with this problem) [See code below]

-- Here I loop thru all frames (blue boxes in scr) (itemFrame is each frame)
itemFrame.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		draggable = true --It is declared in the top of the script and set to false as default
		while wait(0.2) do
			if draggable then					
				itemFrame.Position = UDim2.new(mouse.X, 0, mouse.Y, 0)
			else
				break
			end
		end
	end
end)
				
itemFrame.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		draggable = false		
	end
end)

It registers mouse click and lift but I think the problem is that UIGridLayout is overriding each frame position and makes it unable for the frame to move wherever inside the grid and outside it. So on click, the frame should move where the mouse moves so long player holds the mouse button. How could this be achieved?

I think this is the the most effective solution, is it?

2 Likes

Maybe try taking the frame the player is dragging out of the UIGridLayout whilst its being dragged and then once the player lets go just plop it back into the UIGridLayout?

Thats the most logical solution but youd have to test it to see if it would work or not

1 Like

Probably not the best way of doing it but you could make it so it leaves the frame with the UIGridLayout. Make a folder maybe called “Dragging”
ex:

itemFrame.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		draggable = true 
		while wait(0.2) do
			if draggable then					
				itemFrame.Position = UDim2.new(mouse.X, 0, mouse.Y, 0)
             if itemFrame.Parent ~= Dragging then -- change to where it can be stored while dragging
                   itemFrame.Parent = Dragging
            end
			else
				break
			end
		end
	end
end)
				
itemFrame.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		draggable = false		
        itemFrame.Parent = -- Old location or new one
	end
end)

You are literally waiting for 0.2 seconds just to update the position. RunService.RenderStepped should be used for this.

Sadly this doesn’t seem to work, though I don’t know why. The position seems to change but you can’t see it on the screen. (I’ve tried changing the Z-index) @NeoBuilds thanks for the suggestion, I will change it.

Okay, so to fix this I need to get mouse position in scale of 0 to 1. Is there any way I can obtain mouse position in such a scale?

Turned out that it should be

itemFrame.Position = UDim2.new(0, mouse.X, 0, mouse.Y)

Instead of

itemFrame.Position = UDim2.new(mouse.X, 0, mouse.Y, 0)

@NeoBuilds I don’t think RunService.RenderStepped would work because I need to use a loop here and break out of it which won’t work in RunService? Does while loop provide here good optimization?