Angle not returning less than 1.5 and more than 4.7

I am making a gui where there is an image facing where a dummy is, but the angle doesnt go to the right. The gui item only stays on the left side, and when i turn 360 degrees, it goes to the bottom, then back to the left, when its supposed to wrap around. Basically, the part where AngleRadians is defined, it is only defined to be a part of 1 pi, not 2pi

This is my code:

local RADIUS = 0.5
local ANGLE_OFFSET = 90

	local DetectionNPC = workspace.DetectionNPC.PrimaryPart

	local HumRoot = Character:WaitForChild("HumanoidRootPart")
	local Facing = Character.HumanoidRootPart.CFrame.LookVector
	local Vector = (DetectionNPC.Position - HumRoot.Position).Unit
	local AngleRadians = math.rad(math.deg(math.acos(Facing:Dot(Vector))) + ANGLE_OFFSET)
	local Position = + RADIUS * math.cos(AngleRadians) - Button.Size.X.Scale / 2, 0,
		.5 - RADIUS * math.sin(AngleRadians) - Button.Size.Y.Scale / 2, 0)
	Button.Position = Position
	Button.Rotation = -(math.deg(AngleRadians) - ANGLE_OFFSET)

Basically, there is no difference between say 10 degrees facing left of the detection npc, and 10 degrees facing right of the npc, which means the fix is somewhere in this line of code:

local AngleRadians = math.rad(math.deg(math.acos(Facing:Dot(Vector))) + ANGLE_OFFSET)

I have noticed that the minimum and maximum threshold it goes up/down to is about 1.57 and 4.7, not 0 and 2pi, but im not really a professional at the math functions.

I think the use of the vector Dot is the downfall here. The situation seems underconstrained as there are many vectors that dot with Facing to give the same angle.

I think something like this should work

local VectorCharSpace = (Character.HumanoidRootPart.CFrame:Inverse() * Vector) -- equivalent to CFrame:ToObjectSpace(Vector)
local AngleRadians = math.atan2(VectorCharSpace.Z, VectorCharSpace.X) + math.rad(ANGLE_OFFSET) -- Tune angle offset as required

I may have got a sign wrong with the angle which would lead to the gui rotated the opposite way.

It now wraps around, but there is a weird problem where if i go too far away (like 10 studs) it flips around

fixed the video lol

Ah right yes I think this change would fix it:

local VectorCharSpace = (Character.HumanoidRootPart.CFrame:Inverse() * DetectionNPC.Position).Unit

I think this is equivalent to doing:

local VectorCharSpace = (Character.HumanoidRootPart.CFrame.Rotation:Inverse() * Vector)

but saves having to calculate Vector as an intermediate step

It works perfectly, thank you! :slight_smile:

1 Like