I currently am having issues with my gui as of right now. I want it to have a lerping effect so it lags behind the mouse to make it look better but its having some weird properties when i move past a certain point where it’ll bug out before fixing itself. I’ve tried looking for solutions on other forums but couldn’t find it.
Here’s my current code
Connections.RadialRotationConnection = RunService.Heartbeat:Connect(function(DeltaTime)
local RotationHolder = EmoteUI.Frame.RotationHolder
local MousePos = UserInputService:GetMouseLocation()
local Center = RotationHolder.AbsolutePosition + (RotationHolder.AbsoluteSize * .5)
local Disp = (MousePos - Center)
local Angle = math.deg(math.atan2(Disp.Y - 46, Disp.X))
local FinalAngle = Angle + 90
local CurAngle = FunctionUtils:Lerp(RotationHolder.Rotation, FinalAngle, 0.25)
RotationHolder.Rotation = CurAngle
end)
This does workEdit: forgot about lerp. This does work with the lag effect
--!strict
local run_service = game:GetService("RunService")
local gui_service = game:GetService("GuiService")
local tween_service = game:GetService("TweenService")
local arrow = script.Parent.arrow
local center = script.Parent.center
assert(game.Players.LocalPlayer)
local mouse = game.Players.LocalPlayer:GetMouse()
local function update_rotation()
local mouse_pos = Vector2.new(mouse.X, mouse.Y)
local arrow_center = arrow.AbsolutePosition + arrow.AbsoluteSize / 2
local inset, _ = gui_service:GetGuiInset()
center.Position = UDim2.fromOffset(arrow_center.X + inset.X, arrow_center.Y + inset.Y)
local direction = (mouse_pos - arrow_center)
local angle = math.atan2(direction.X, direction.Y)
local new_angle = -math.deg(angle) + 90
if math.abs(arrow.Rotation - new_angle) > 180 then
new_angle += 360
end
arrow.Rotation = tween_service:SmoothDamp(arrow.Rotation, new_angle, 0, .05)
end
run_service.PreRender:Connect(update_rotation)
This is happening because your lerp function is trying to interpolate from A to B, where A and B do not connect. But when lerping angles, A and B do connect.
Imagine your angle is at 350 degrees, and the next target angle is 10 degrees. The ideal interpolation would rotate +20 degrees. However, a normal lerp will interpolate -340 degrees instead. It has no concept that it can lerp forward to get to 10 degrees from 350.
Thankfully, we can write a lerp function that properly deals with angles. It properly wraps the value around the 360 degree mark. This can be directly swapped out for your FunctionUtils:Lerp function:
local function LerpAngle(from: number, to: number, alpha: number): number
local diff = math.fmod(to - from, 360)
diff = math.fmod(diff * 2, 360) - diff
return from + diff * alpha
end
-- ...
local CurAngle = LerpAngle(RotationHolder.Rotation, FinalAngle, 0.25)
A couple notes:
To make your code non FPS-dependent, see Freya Holmer’s post about lerping with delta time correctly.
The LerpAngle function above assumes degrees. For radians, swap out the two instances of 360 with math.pi * 2.
Here’s an implementation of Holmer’s framerate-independent method along with the above LerpAngle function:
local function SmoothLerpAngle(from: number, to: number, dt: number, h: number): number
return LerpAngle(from, to, 1 - math.exp(-dt / h))
end
-- ...
-- 0.2 is the "halflife" (smaller value is quicker movement)
local CurAngle = SmoothLerpAngle(RotationHolder.Rotation, FinalAngle, DeltaTime, 0.2)