Making speed of tween adapted to distance in UI


I have this ui bar:

And basically what i’m doing is placing the arrow on a random position based on an IntValue, and then tween that value to determine the arrow’s position. However, if i just give in 1 as tweentime for the value, it will be very slow or quick, depending on the distance. I know it is possible to avoid this with vectors by using Magnitude, but how would i handle it with UDim2?

Thanks in advance!

It’s probably possible to use the AbsoluteSize of the parent Frame, multiplied by the Scale of the Position of the arrow, and then doing the same thing but multiplied by the Goal position’s scale. Having the two products, subtract them and use math.abs to remove negative values. Finally, divide by a large number (if the size is 1000 pixels wide, a number of 500 will get a quotient of 2) to get a small number for the time. Something like this (typed on a phone, not tested.)

local Bar_Size = <AbsoluteSize of parent Frame, updated when it changes>
local Current_Arrow_Position = <Position.X.Scale of arrow, updated when it changes>
local Target_Arrow_Position = <UDim2.X.Scale of goal>

local Distance = math.abs((Bar_Size * Current_Arrow_Position) - (Bar_Size * Target_Arrow_Position))

local Time = Distance / 500 -- Bigger number size makes Tweens faster.

local Tween_Info =, <other stuff>)

TweenService:Create(Arrow, Tween_Info, Goal):Play()

It’s also possible to cut many steps and just divide the Arrow’s current X Scale position to the goal’s X Scale position, then multiply or divide based on how fast or slow you want it to go.

1 Like

When you place the arrow on the GUI, you’re probably setting its position to, 0, 0, 0) or similar.
That means the arrow’s position can be anything between 0 to 1.
The UDim2 is merely that position (a simple number) turned into a UDim2, you don’t really need to do anything to it.

To get the distance that the arrow moves, you simply do math.abs(old - new).

To compensate for this distance, you simply multiply the tween’s time with this distance.

If the arrow was in the center and the new position is also the center, then the tween’s time will be 0 and the tween will finish instantly because it doesn’t need to move.
If the arrow is on one end and it needs to move to the other end, then the difference will be 1. 1 * 1 is 1, and so the arrow will take 1 second to move to the other end.

tl;dr just multiply the time by the distance moved

With UDim2, you only have to look at Udim2.X.Scale, for your case.
Time is equal to distance over velocity, so:

d = math.abs(finalRandomPosition.X.Scale - initialPosition.X.Scale)
v = 15
t = d/v