How to position a GUI at the mouse's location?

Hello!

I have recently been trying to position a frame wherever the player clicks
Here’s what I did:

OBJECT HIERARCHY:

  • StarterGui/ScreenGui

  • StarterGui/ScreenGui/Button

  • StarterGui/ScreenGui/Button/LocalScript

  • StarterGui/ScreenGui/Button/Frame

Then I tried two methods…
First one was relatively simple:

local button = script.Parent
local frame = button:WaitForChild("Frame")
local userInputService = game:GetService("UserInputService")

button.MouseButton1Click:Connect(function()
	local pos = userInputService:GetMouseLocation()
	frame.Position = UDim2.fromOffset(pos.X, pos.Y)
end)

The achieved result was this

That didn’t work either, for some reason…
So I tried a little different approach:

local button = script.Parent
local frame = button:WaitForChild("Frame")
local userInputService = game:GetService("UserInputService")

button.MouseButton1Click:Connect(function()
	local pos = userInputService:GetMouseLocation()
	local relativePosition = pos - frame.Parent.AbsolutePosition
	frame.Position = UDim2.fromOffset(relativePosition.X, relativePosition.Y)
end)

I got the exact same result.
Both cases, the frame was position well above the click.

I don’t understand why.

Any help would be appreciated.

Kind regards,

Wiscript

7 Likes

I recommend using Player:GetMouse() like this:

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Mouse = Player:GetMouse()

local PlayerGui = Player:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local MyButton = ScreenGui:WaitForChild("Button")
local MovingFrame = MyButton:WaitForChild("Frame")

MyButton.MouseButton1Click:Connect(function()
    local positionToAssign = UDim2.new(0, Mouse.X, 0, Mouse.Y)
    MovingFrame.Position = positionToAssign
end)

Also, make sure your MovingFrame has an Anchor Point property of Vector2<.5, .5>. Let me know if this doesn’t achieve a better result and I think I know another solution.

1 Like

I achieve the same result when using :GetMouse()

The MovingFrame instance in my example must be removed as a child of the button instance. It must instead be another child of the ScreenGui. This is likely the issue since calculated position is relative to the parent within which a Gui Instance is rendered. If I re-did the hierarchy I would do this:

ScreenGui → Children: Frame of Size UDim2.new(1, 0, 1, 0) → Children of full-screen frame: Button and MovingFrame

I think the problem is your not accounting for the topbar offset, when the mouse position accounts for it automatically

to fix that you should do

frame.Position = UDim2.new(0, pos.X, 0, pos.Y - 36)

You also may want to account for the size of the square, if you want it to be in the center of the Mouse


also:
don’t use Player:GetMouse() like some have said because it is becoming more obsolete as UserInputService is a better option

21 Likes

How could I make it so that there are box bounds. As in there is a limit as to where the box can move too

use math.clamp to do it