How does the trigonometry in this script work?

  1. What do you want to achieve? Keep it simple and clear!

Understand Trigonometry in script.

  1. What is the issue? Include screenshots / videos if possible!

This script makes the characters head rotate relative to your cameras position. But I do not get how the trigonometry works.

I get that arcsine of opposite/hypotenuse = degrees, but why is the opposite site of the triangle the x and then the y coordinate of the cameras lookvector? From what I understand you make a vector from the humanoidrootpart to the camera and then get the cameras lookvector but I dont understand what happens after this (see picture). Thanks for the Help!

local camera = workspace.CurrentCamera

local character = game.Players.LocalPlayer.Character
local root = character:WaitForChild("HumanoidRootPart")
local neck = character:FindFirstChild("Neck", true)
local yOffset = neck.C0.Y

local CFNew, CFAng, asin =, CFrame.Angles, math.asin

	local cameraDirection = root.CFrame:toObjectSpace(camera.CFrame).lookVector

	if neck then
		neck.C0 = CFNew(0 , yOffset, 0) * CFAng(0, -asin(cameraDirection.x), 0) * CFAng(asin(cameraDirection.y), 0, 0)
  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

Tried looking at the devforum for trigonometry in 3d space.

1 Like

The function is measuring the angle of the look vector from the Z axis

The Z axis represents the LookVector of the root part, X axis the RightVector, and Y axis the UpVector. This is due to the ObjectSpace function.

The hypotenuse is the look vector itself which is a unit vector with a length of 1.

The opposite side is the horizontal x axis component of the look vector.

There the angle theta is measured with asin.

Same thing goes for the up and down y axis except it’s on the Z and Y axis coordinates of the rootPart.


Technically the trig in the code in question is slightly wrong for the yaw (Y axis) rotation.

The hypotenuse of the triangle @dthecoolest drew is not “the LookVector”, but rather “the LookVector when it’s y component is 0”, which probably does not have a length of 1.

So to use sine like that you’d need to do

local x, y, z = cameraDirection.X, cameraDirection.Y, cameraDirection.Z
local hyp = math.sqrt(x*x + z*z)
local yaw = math.asin(x / hyp)

Or just use arctangent instead:

math.atan2(-x, z)

The pitch one (math.asin(y)) is correct because the hypotenuse is actually the look vector, while the “opposite” side is indeed cameraDirection.Y


Thanks for pointing this out :+1:,

I was worried with overcomplicating things.

For @SejeBlomst and others it is important to take note that a lot of trigonometry is approximated especially for procedural animations as accuracy and proper maths isn’t the goal.

It’s purely for animation purposes.

Another example of improper trig below :point_down:

If you want to see accurate angle measurements I recommend looking at turret scripts like this one made by @ThanksRoBama which uses atan2 as @nicemike40 has mentioned for both the pitch and yaw axis.

These scripts are the ones that need to be precise and use proper trigonometry to achieve the accurate effect of pointing to the target.