How to use scaling and offset in scripts

I am trying to make a mouse cursor by moving an imagelabel to the actual mouse when they are hovering a textbutton.
People use this simple renderstepped event. Very easy to understand and impossible to understand.

game:GetService("RunService").RenderStepped:Connect(function()
	icon.Position = UDim2.new(0, mouse.X, 0, mouse.Y)
end)

To my knodwledge, this only works if you’re having everything above the imagelabel in offset - which is useless when making an actual game, as the UI would be all over the place on a different device. How do people make games with offset? How is this method ever possible? I’m very confused on why offset is even a thing, and why it then also seems to be the only option to move an imagelabel.

I then tried to move it with scale after realising it could be the issue. I don’t even know if that is the issue, but since no one seems to know I tried to read up on how to move it. This is the only thing I could find and it just gives an error that Scale cannot be assigned to Position.

game:GetService("RunService").RenderStepped:Connect(function()
	icon.Position.Scale = UDim2.new(mouse.X, 0, mouse.Y, 0)
end)

The simple quesiton for this post is how to use scale in this situation or/and why/how using offset is an axis measurement to begin with.


From some viewport frame models being cut off randomly, clickdetectors activation distance rounding down to 0 after going below 25 and clickdetectors randomly not working for some models - UIs make no sense to me. Reading things on don’t solve any of the issues I have and most of them don’t get answered when posting and never existed on devforum in the past. I have found that scripting in studio has become a lot easier when I got better, but if the scripts relate to the UI then I am like a baby because they seem to be devoid of the logic used in 1 dimensional scripting.

There must be some basic knowledge I’m missing to solve these things. Maybe my understanding of scaling and offset are misslead, and maybe clickdetectors have hidden physics dependant properties that cause them to act seemingly randomly. It’s true I am far from a good programmer, but I can at the very least understand, implement and sometimes create less basic scripts. And even so, UIs are killing my drive to make anything.

1 Like

For this case, you shouldn’t use Scale (except for maybe the ImageLabel size?), since the mouse.X and mouse.Y are actually the current pixel location the cursor is currently on, so it wouldn’t ever be outside on a smaller screen since the mouse is always constrained within the size of the screen.

Position.Scale is a read-only value. To set the scale instead, just do icon.Position = UDim2.new(mouse.X, 0, mouse.Y, 0) OR icon.Position = UDim2.fromScale(mouse.X, mouse.Y) which skips the offset values (there’s also UDim2.fromOffset)

Offset is basically just a constant pixel offset that doesn’t take into account screen size. You set it to 25, it moves/scales 25 pixels on ALL screens, this is bad for some cases where you don’t want your gui to be out of the screen or look too big/small on smaller/bigger monitors than yours, but it’s good if you need to place something at one specific location (in this case, at the mouse’s position) or need it to always have the same offset.

Scale is a range from 1 to 0 that means basically the percentage of the screen (OR the parent of the frame/object if it’s not parented only to a ScreenGui) (ej: if it’s at 0.5, it means at the 50% of the screen, if its 1, then it means 100%, etc…) and it’s always based on your resolution, so it conserves the size and positioning to ALWAYS be the same on every screen. You can also use plugins to do this automatically, like AutoScale

Just a small additional tips, you can directly use this to setup full offset or full scale Ui objects.

UDim2.fromScale(mouse.X, mouse.Y)
UDim2.fromOffset(mouse.X, mouse.Y)
2 Likes

I don’t get what you mean. You are saying that I shouldn’t use scale, but by using offset the result will be that the imagelabel is in a wrong position when using a different device. When I go to a game on Roblox, the UIs aren’t all over the place, but if I try to do this with offset textbutton, the result will be that it will be all over the place in the test tab. So no dev is using offset to my understanding.

For the issue itself - the scale doesn’t work. The imagelabel is not there…

Edit: Also the imagelabel does appear if you divide the values by 1000, however the imagelabel also moves with 1/1000 speed so it’s not that useful

I mentioned that since the mouse.X and mouse.Y are the current pixel position (offset), in this case you HAVE to use offset instead of scale, and it won’t be in the wrong position or look weird in different screens because that position can only be within the screen

Partly correct, a lot of devs use scale more often than they use offset, but even Roblox uses offset instead of scale (ej: the topbar, toolbar, etc…, they don’t use scale exclusively)

I’m saying you shouldn’t use it on this case in particular, since you need to place the cursor image in a specific point of the screen, however that isn’t the case for most other things.
You should check another post for info ab this, because I’m not very good at explaining things correctly, sorry

Sorry for not clarifying, I wrote that as an example of setting the scale on a gui object and not for actual use but you shouldn’t actually use that on this code, because it will just simply be out of the screen at all times, use offset instead

If I do it with offset this issue comes. As you can see, the imagelabel is in the bottom right corner, but it should be in the middle (yellow means the player is hovering). This is why I tried using scaling, because offset seems to not be correct .-.

Question, does the image label move at all if you move your cursor? Maybe you aren’t updating the position?

EDIT: I just wrote a script, and it works without any issues, not sure what else could be the problem here, sorry.

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

local cursor = script.Parent
RunService.RenderStepped:Connect(function()
	local currentMousePosition = UserInputService:GetMouseLocation()
	cursor.Position = UDim2.fromOffset(currentMousePosition.X, currentMousePosition.Y)
end)

ok tested it and it gives same results. Mouse is in bottom right corner.
is using UIS different from just getting the mouse’s udim values?

Just tried this, yes, but, not by much (the mouse position is off if you don’t use the gui inset). The mouse values only work correctly if IgnoreGuiInset on the screen gui is set to false, meanwhile UserInputService respects it.
Imo you should use UserInputService and turning on IgnoreGuiInset since the Mouse is actually a deprecated object

well I did try your script and with and without IgnoreGuilnset it gives same results .-.
kind of odd that it decides to be in the bottom right corner specifically. are you using scaling or offset for the texbutton and imagelabel?

Structure

image

Hover button properties

The cursor is using only offset as written in the script.


Here are both guis if you need to try them:
test stuff.rbxm (6.7 KB)

1 Like

It looks like the issue was that I was keeping them in 1 screengui.

There is still an issue though. The imagelabel seems to be a bit inacurate. Not sure why. I mean the mouse is not that big so its area where the imagelabel could attach itself to wouldn’t be big enough to cause this much inaccuracy.

Can you send the rest of the script?

local target = script.Parent
local icon = script.Parent.Parent.Parent.Parent:WaitForChild("ScreenGui2").ImageLabel

target.MouseEnter:Connect(function()
	icon.Visible = true
	game:GetService("UserInputService").MouseIconEnabled = false
	target.BackgroundColor3 = Color3.fromRGB(255, 255, 127)
end)

target.MouseLeave:Connect(function()
	icon.Visible = false
	game:GetService("UserInputService").MouseIconEnabled = true
	target.BackgroundColor3 = Color3.fromRGB(0, 255, 127)
end)

target.MouseButton1Click:Connect(function()
	target.BorderSizePixel = 5
	wait(1)
	target.BorderSizePixel = 0
end)


local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

RunService.RenderStepped:Connect(function()
	local currentMousePosition = UserInputService:GetMouseLocation()
	icon.Position = UDim2.fromOffset(currentMousePosition.X, currentMousePosition.Y)
end)


(forgot to mute the music)
Seems to be working just fine for me.
Are you resizing the cursor? If that’s the case, then change its anchor point to be 0.5, 0.5 so it scales from the middle instead of the top left

its anchor point is 0.5, 0.5
(hovering the lowest point of the button) For some reason 0.5, 0.5 is not in the middle, but middle top

It works completely fine to me even with all the changes. Maybe you’ve structured your gui wrong or messed up some properties? I actually can’t seem to find out what’s causing it, sorry.
Could you send the gui as an rbxm? Right Click then Save as File and just drag and drop it

1 Like

gui.rbxm (6.4 KB)


Maybe the problem is within ScreenGui2 (which your file doesn’t have). It seems to be working properly however if I make a ScreenGui with that name and a image label in it

1 Like

lol it doesn’t have the ignoreguilnset on… Thanks for being patient.
I would never have thought of changing position of imagelabel, since I had no idea it needs to be in a different screengui.

1 Like