Angles not making sense between two vectors


	local CLookVector = DotTester.CFrame.LookVector --Look vector is always the 'level' we want
	local CurrentLookVector = CLookVector.Unit
	 
	
	local TestVector = Vector3.new(CLookVector.X, player.Position.Y, CLookVector.Z) -- x,y,z -- want the Y value to match, doesn't matter which 'level' it's brought to on the Y

	local VectorToPlayer = (DotTester.CFrame.LookVector - player.Position)-- would also need to be modified by the same Y value
	
	local dotProduct = CurrentLookVector:Dot(VectorToPlayer)
	
	
	local magnitude = (player.Position - DotTester.Position).Magnitude
	local laserSize = Vector3.new(1,1,magnitude)
	
	local modPlayerPos = Vector3.new(player.Position.X, DotTester.Position.Y, player.Position.Z)
	
	local firedLaserPos = (modPlayerPos + DotTester.Position)/2
	
	local laserFinalPos = CFrame.new(firedLaserPos, modPlayerPos)
	local staticLaserPos = CFrame.new(DotTester.Position, DotTester.CFrame.LookVector)--construct a cframe from a vector3 point, then a facing value. 
	
	local AmendedLookVector = Vector3.new(DotTester.Position.X, DotTester.Position.Y, DotTester.Position.Z)--might matter for final ray calculation, considering the midpoint
	
	moveLaser(laserSize, laserFinalPos)--  
	
	movePart2(laserSize, CFrame.new(AmendedLookVector, DotTester.Position + DotTester.CFrame.LookVector)) 
	
	------
	------
	------
	local vector1 = workspace.raytest1.Position - DotTester.Position
	local vector2 = workspace.raytest2.Position - DotTester.Position
        local vector1 = vector1.unit
        local vector2 = vector2.unit

	
	local dot = vector1:Dot(vector2)
	local degrees = math.deg(math.acos(dot))

In short, I am struggling to understand vectors, and how to get the angle of difference on a 2d plane between two 3d vectors. The dot product on normalized vectors with .unit returns nan(ind) for me, so I am clearly using vectors incorrectly when trying to find the dotproduct.

I have read through every single thread I can find and it appears that every answer is wrong that I have found so far, you cannot actually calculate an angle with 2d vectors with the dot product equation… so what am I missing?

In the given example, vector1 and vector2 should be right angles, and therefore return 0, however I get nan(ind), regardless of where the blocks are moved when the loop runs.

There’s a lot of vectors going on here so I’m not sure what exactly is wrong, but you’re final two lines are indeed the right way to calculate an angle between two vectors.

So one of your vectors is probably zero length?

Try printing them or visualizing them with some gizmo plugin or something.

I don’t really understand what your code is doing, but it works fine once you get the vectors right.

The problem lies in VectorToPlayer, I think

A simple rule of thumb to calculate angles using dot product is both vectors must be normalized first.

Basically, vectors are arrows.
.Position property refers to an arrow pointing from the origin (0,0,0) to the part’s center.

If you subtract positionA - positionB, you get an arrow pointing from positionB to positionA

If you subtract cframe.lookVector - positionB, (which is what you did in the code) you get an arrow pointing from positionB to somewhere near the origin, since cframe.lookVector is always 1 stud away from origin (Magnitude 1)

Here’s an example of working code from the code you gave

local DotTester = script.Parent.dotTester
local player = script.Parent.player
local CLookVector = DotTester.CFrame.LookVector --Look vector is always the 'level' we want
local CurrentLookVector = CLookVector.Unit

local function Debug()
	local TestVector = Vector3.new(CLookVector.X, 0, CLookVector.Z) --flat lookAt

	local VectorToPlayer = (player.Position - DotTester.Position)-- would also need to be modified by the same Y value

	local dotProduct = CurrentLookVector:Dot(VectorToPlayer.Unit)


	local magnitude = (player.Position - DotTester.Position).Magnitude
	local laserSize = Vector3.new(1,1,magnitude)

	local modPlayerPos = Vector3.new(player.Position.X, DotTester.Position.Y, player.Position.Z)

	local firedLaserPos = (modPlayerPos + DotTester.Position)/2

	local laserFinalPos = CFrame.new(firedLaserPos, modPlayerPos)
	local staticLaserPos = CFrame.lookAt(DotTester.Position, DotTester.Position + VectorToPlayer)--construct a cframe from a vector3 point, then a facing value. 

	local AmendedLookVector = DotTester.Position--might matter for final ray calculation, considering the midpoint
	
	local new = Instance.new("Part")
	new.Parent = script.Parent
	new.CFrame = laserFinalPos
	new.Size = Vector3.new(1, 1, magnitude)
	new.Anchored = true
	new.Material = Enum.Material.Neon
	game.Debris:AddItem(new, 1)
	
	local new2 = Instance.new("Part")
	new2.Parent = script.Parent
	new2.CFrame = CFrame.lookAt(AmendedLookVector, AmendedLookVector + DotTester.CFrame.LookVector*2) * CFrame.new(0,0, -5)
	new2.Size = Vector3.new(.8, .8, 10)
	new2.Anchored = true
	new2.Material = Enum.Material.Neon
	new2.Color = Color3.new(0.3,0.5,1)
	game.Debris:AddItem(new2, 1)
	--moveLaser(laserSize, laserFinalPos)--  

	--movePart2(laserSize, CFrame.new(AmendedLookVector, DotTester.Position + DotTester.CFrame.LookVector)) 

	------
	------
	------
	local vector1 = new.Position - DotTester.Position
	local vector2 = new2.Position - DotTester.Position
	local vector1 = vector1.unit
	local vector2 = vector2.unit


	local dot = vector1:Dot(vector2)
	local degrees = math.deg(math.acos(dot))
	return degrees
end

while true do
	print("DEGREES: ", Debug())
	wait(0.4)
end
1 Like

Thank you very much for taking the time to go through this. I was not understanding which vectors I wanted to begin with and you did an awesome job showing me!

You’re welcome, glad it helped.

For anyone who ends up struggling with this as much as I did, here is the solution to isolating an angle on a 2d plane, from 3d vectors:


while true do
	
	--getDegrees(newXVectorZ, newYVectorZ)
	local vector1 = PartX.Position - PartZ.Position
	local vector2 = PartY.Position - PartZ.Position -- where Z is the center
	
	local vector1 = vector1.unit
	local vector2 = vector2.unit
	--these corrected vectors isolate the angle to the XZ plane, getting the 'horizontal' angle between points
	local correctedVector1 = Vector3.new(vector1.X, vector2.Y, vector1.Z)
	local correctedVector2 = Vector3.new(vector2.X, vector2.Y, vector2.Z) 

	print(tostring(correctedVector1).."  VERSUS  "..tostring(vector1)) -- so you can it is the same value
	print(tostring(correctedVector2).."  VERSUS  "..tostring(vector2))
	wait(1)
	
	local dot = correctedVector1:Dot(correctedVector2)
	local degrees = math.deg(math.acos(dot))
	print(degrees)
	
end