Hey all. So I have this simple code that allows me to get an angle between a part’s position + direction, and a point in the world.
My current technique only returns angles in the interval [0; pi] because two vectors can never point more away from each other than directly away from each other, which can always be achieved by a rotation of pi radians = 180 degrees . This means the angle you get in this way has no direction (it’s never negative). How can I fix this?
The part here is facing ‘right’ away from the red block and returns a positive angle value (which is good)
But this time, the part here is facing ‘left’ away from the red block and STILL returns a positive angle value (I need it to return a negative value in this case. How do I fix this?)
local function GetAngleBetween(PosA, PosB)
return math.acos(math.clamp(PosA:Dot(PosB), -1, 1))
end
while true do
wait()
local CameraLookVector = script.Parent.CFrame.LookVector
local LookToPoint = (workspace.RedBlock.Position - script.Parent.Position).Unit
local AngleBetween = GetAngleBetween(CameraLookVector, LookToPoint) -- In radians
print(AngleBetween) -- Always returns a positive value which is the problem.
end
no. Both. Both of them have an angle difference of 40 degrees. which is the problem. The one facing left should be -40, but the code will always return a positive angle value
You could just normalize the LookVector.X to -1 or 1 and multiply it by your angle. I’m not sure if their is a better way of doing this but here’s a quick and easy example of what I mean.
local sign = math.clamp(part.CFrame.LookVector.X * 10, -1, 1)
sign = if sign == 0 then 1 else sign
Edit: Forgot to account for situations in which the player is facing directly towards or away from the point (where the value would be equal to 0).
By sideways, do you mean you stay facing the point but move to the left and right? And in such situations you’d like it for the value to be negative if the player is on the left-hand side of the point and vice-versa for the right-hand side?
What about this situation where the blue part is facing the red part and coming from the opposite side. Do you want it to then flip the sign? Where this would result in a positive angle because from the blue part’s perspective it is on the right side?
In that situation, the blue part’s arrow is going left from it’s perspective. Therefor, it should be a negative value. Think of changing an angle value in roblox’s hinges. It’s supports negative and positive numbers for directional reasons.
Well if you just want to know where the part is on the left or right side of the point, from a top-down perspective, you can just compare the x values.
local x = math.clamp(part.Position.X - point.Position.X, -1, 1)
x = if x == 0 then 1 else x
tan=opposite/adjacent. You could you lookVector to determine the player/camera direction to decide if x or z is the opposite or hypotenuse. Personally, this is what I did for a angle list script to prevent drag with position, by forcing it to an angle that wouldn’t have drag if it was below that angle and then lowering the angle when it got near.
local Xdifference = (CameraPointPosition.X - RedBlock.Position.X)
local Zdifference = (CameraPointPosition.Z - RedBlock.Position.Z)
local angle = math.atan(Xdifference/Zdifference) -- can change depending on direction
What I would do is make a fake cframe to make to object space based off of both the parts like so
this might help to change the look to point by changing it on the red part exactly
local Fake = CFrame.lookAt(BlueBlock.Position,RedBlock.Position)
local LookToPoint = Fake.Position + Fake.Lookvector
There’s literally no LookVector or CFrames in your provided code. Do I have add something else onto this or use this in my current code somewhere or am I missing a curtail step to this?
Well you can figure that out but I’ll write it out for you.
tan0=opposite/adjacent
function getDirectionalTan(PerspectiveCFrame, XDistance, ZDistance)
local tan = 0
local lookVectorX = math.abs(math.round(PerspectiveCFrame.lookVector.X))
if lookVectorX == 0 then--Player looking x direction so use Z as opposite, and X as adjacent
tan = (ZDistance/XDistance)--tan number
else--Looking z direction so use X as opposite, and Z as adjacent
tan = (XDistance/ZDistance)--tan number
end
return tan--return tan number
end
function getAngle(CameraCFrame, PartPosition)
local CameraPosition = CameraCFrame.Position
local XDistance = PartPosition.X - CameraPosition.X
local ZDistance = PartPosition.Z - CameraPosition.Z
local angle = math.atan(getDirectionalTan(CameraCFrame,XDistance, ZDistance))--Run tan math function
return angle
end
local angle = getAngle(Camera.CFrame, Part.Position)--fix paraemetre to ur variables, and tadaaa