Calculate the angle between 2 3D vectors

I’m trying to calculate the angle between 2 vectors, but the angle isn’t too accurate. And if I move the other vector to aside, the math started to act weird.

What’s I’m trying to achieve:

Code:

local p1, p2 = workspace.p1, workspace.p2

while task.wait(1) do
	local mag = p1.Position.Magnitude * p2.Position.Magnitude
	local angle = math.deg( math.acos( p1.Position:Dot(p2.Position) / mag ) )
end

It works, but not precise. If you can, please help me improve it.

Why improve it? Whats wrong with it.

Like what I said, it’s not too presice and not working perfectly. Assuming the angle of this picture should be 0 because they are next to each other:
image|591x29, 50% 4, 50%
You can see it prints 7.73 degrees for that

What I’m trying to achieve here is to calculate the angle between a player - another player in a specific range (kinda like the center of a circle):

And let’s say there’s a point on the circle (another player):

Now I’d find the angle from the current player to the other one for other things for my game. The distance between the 2 is the vector within the maximum range (the formula would be: cos^1 = (magnitude / range) or vice versa)
Hope this help you understand what I mean, if you need more please tell me.

Do you mean the vector between the two parts, and the vector (1, 0, 0) (or some other fixed vector)?

Anyway, seems like the error is that you’re mixing up the points that define the first vector, and this vector itself.

image

function vectorAngle(v1: Vector3, v2: Vector3): number
    return math.acos( v1:Dot(v2) / v1.Magnitude * v2Magnitude )
end

function vectorAngleToRight(v: Vector3): number
    local right = Vector3.FromNormalId(Enum.NormalId.Right)
    return vectorAngle(v, right)
end

function pointsAngleToRight(p1: Vector3, p2: Vector3): number
    return vectorAngleToRight(p2 - p1)
end

while wait() do
    print(math.deg(pointsAngleToRight(partA.Position, partB.Position)))
end

Keep in mind that using this formula, you will never get negative angles or angles above 180 degrees = math.pi r, and the angles to the green and orange vectors in this example would both be positive 45 degrees:

You should think of the vector angle formula you’re using as “how much do I have to rotate one vector around any 3D axis to get to the other vector”. Since it can be around any axis, the green and orange vectors are actually rotated the same amount but around parallel but opposite axes. If you want to distinguish between rotations “to the left and to the right”, you can’t use this formula. You’ll need to use atan2 instead, plus you’ll need a third vector to define the plane you want to get the rotation in / the axis you want to get the rotation around.

You’re misinterpreting the geometric definition of the dot product. if a unit vectors magnitude is 1 and the dot product can be defined as the cosine of their angle times the product of their magnitudes then it should be

math.deg(math.acos((p1.Position-p2.Position).Unit:Dot(p1.LookVector)))
2 Likes

It sort of looks like you don’t want to include vertical offsets, in which case you could do

local offset = p2.Position - p1.Position
local angle = math.atan2(offset.Z, offset.X)

That will give you an angle between -π and π

3 Likes

Should it be p2.LookVector instead of p1.LookVector?

Yeah, it should given the context of the image assuming p1 is blue and p2 is red. If it weren’t it would be the angle + 180 degrees. TBH I wouldn’t recommend getting angles from two vectors with the whole cosine trick as it only really works if your vectors are in the first quadrant. Developers created atan2 so you don’t have to deal with the sign/direction of the vector.

1 Like