Fastest path to tween in gui degree rotation

I’m currently making a mordhau-style directional combat system thing, and i’m making the arrow pointer point towards the input delta (displayed by the white square). It all works well except when tweening.

When tweening from for example 280 degrees → 10 degrees, it takes the long way around instead of just going like 280 → 360 → 0 → 10, which makes complete sense it’s just not what I want and I’m not sure how to fix it.

I know this is a common problem and I saw something about it long ago but I can’t find any documentation on it because I forgot what the better method was called, and I don’t know if it exactly applies to a single axis like a gui or not.

What I want:

What I get:

local UserInputService = game:GetService("UserInputService")
local tweenService = game:GetService("TweenService")

UserInputService.InputChanged:connect(function(input)
	local unitVector2 = Vector2.new(0.482, 0.472) + Vector2.new(input.Delta.X * 0.05, input.Delta.Y * 0.05)
	
	-- Stats
	script.Parent.Parent.Pos.Text = tostring(input.Position)
	script.Parent.Parent.Delta.Text = tostring(unitVector2)
	
	-- Delta Frame
	tweenService:Create(script.Parent, 
		TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), 
		{Position = UDim2.new(unitVector2.X, 0, unitVector2.Y, 0)}):Play()
	
	-- Pointer
	tweenService:Create(script.Parent.Parent.Pointer, 
		TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), 
		{Rotation = (math.atan2(input.Delta.Y, input.Delta.X) * (180/math.pi)) - 90}):Play()
end)
1 Like

Interesting problem, here’s my solution.

Solution
local UserInputService = game:GetService("UserInputService")
local tweenService = game:GetService("TweenService")

function angleBetweenSigned(vector1, vector2)
	local x1 = vector1.X
	local x2 = vector2.X
	local y1 = vector1.Y
	local y2 = vector2.Y
	local angle = math.atan2(x1*y2-y1*x2,x1*x2+y1*y2)
	return -angle
end

UserInputService.InputChanged:connect(function(input)
	local unitVector2 = Vector2.new(0.482, 0.472) + Vector2.new(input.Delta.X * 0.05, input.Delta.Y * 0.05)

	-- Stats
	--script.Parent.Parent.Pos.Text = tostring(input.Position)
	--script.Parent.Parent.Delta.Text = tostring(unitVector2)

	-- Delta Frame
	tweenService:Create(script.Parent, 
		TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), 
		{Position = UDim2.new(unitVector2.X, 0, unitVector2.Y, 0)}):Play()

	-- Pointer
	local pointer = script.Parent.Parent.Pointer
	--Assumes when rotation = 0 degrees, gui arrow is pointing up
	local pointerDirection = Vector2.new(math.sin(math.rad(pointer.Rotation)),math.cos(math.rad(pointer.Rotation)))
	local deltaDirection = Vector2.new(input.Delta.X, -input.Delta.Y)

	local additionalAngle = angleBetweenSigned(pointerDirection, deltaDirection)
	additionalAngle = math.deg(additionalAngle)	

	tweenService:Create(pointer, 
		TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), 
		{Rotation = pointer.Rotation+additionalAngle}):Play()
		
end)

How it works is that I converted the GUI.Rotation into a vector2, then found the input delta and converted it into a vector2 then used this angle between vectors formula I found online in the MatLab Forum to find the angular difference between the two vectors whether to rotate clockwise or counterclockwise then I just add this to the current pointer rotation and tell the tweenservice to tween it into that direction.

6 Likes

Oh wow! Well it very obviously works, I’ll be taking my time to understand this for now because brain smooth. Thank you!

1 Like

Can u share the code pls pls :frowning:

It’s already there under the drop down menu?

The key is basically this line of code:

So instead of 240 degrees to 1 degree in rotation which will rotate the other way it adds it up 240 + 121 degrees.