Rotating parts using trigonometry

I learned about trigonometry, And was pretty easy but How can I apply them to Roblox

I thought about converting 3D to 2D to make it easy to apply it.
I tried rotating a part depending on how you rotate your camera on the y axis and so should the part rotate here is my code so far

local Cam = workspace.Camera
local LookVector = script.Parent.CFrame.LookVector
local Part = script.Parent

while task.wait(0.01) do

	local Angle = math.atan(LookVector.X/Cam.CFrame.LookVector.Y)
	Part.CFrame = CFrame.new(Part.Position) * CFrame.Angles(0,math.pi/2,Angle)
	
end

However when I try this the part rotates in the wrong axis hitting for some reason a limit of like 60 degrees
I tried so many things to get it working but it doesn’t work

I have some trouble understanding why math.atan doesn’t return nun while others do although
LookVector and Cam LookVector aren’t equal to zero


I am trying to get the angle using Cam LookVector and Part LookVector
So, What I need is a math function that needs both of the adjacent and Hypotenuse
Then why math.acos doesn’t work

I am so confused. I would really appreciate it if anyone clears up my confusion

Keep in mind that I am new to trigonometry

I am still looking for some explanation

What is your goal? Do you want the part to rotate locally depending on player’s camera Y rotation?

Yes that’s exactly what I want. sorry if I wasn’t clear about what I want

If you want the part to rotate locally, you need to use local script so the part is positioned differently for each player. I created a local script in game.StarterPlayer.StarterPlayerScripts and put the following local script inside:

local Part = game.Workspace:WaitForChild("RotatingPart")
local LookVector = Part.CFrame.LookVector

while true do
	task.wait(1)
	local Cam = game.Workspace.Camera
	local Angle = math.atan(LookVector.X/Cam.CFrame.LookVector.Y)
	Part.CFrame = CFrame.new(Part.Position) * CFrame.Angles(0,math.pi/2,Angle)
end

The part seems to be rotating in the axis you wanted to.
Note: I made the script update the part’s rotation every 1 second for the convieniece of testing.
If that’s not what you wanted, let me know.

2 Likes

I am asking for explanation not just code like
Why you used math.atan instead of math.acos?
Why math.acos doesn’t work?
The part position and rotation is going to be the same for everyone so I don’t think there is a need of using local script

math.atan returns arc tangent of the number
math.acos returns arc cosine of the number
Those are two different functions that return 2 different numbers.

Isn’t math.acos supposed to take the adjacent divided by hypotenuse to get the angle
Why in my case that doesn’t give me the right angle?

  1. Arctangent takes components base and height, which is known by the X and Y value.
  2. Arccosine requires the hypotenuse and base, It could be used if you do 1/X I believe.
  3. A local script is needed to access the player’s camera.
    I am confused exactly by what you want, do you want a part that tilts down/up at the same angle as the camera?
1 Like

what I want is the part to tilt up and down as the camera So do you need any things to clarify about what I want?

You probably got confused by how I want the camera to tilt without a local script cuz I am running the game to play testing with a character however that’s not the main point
I need explanation on Why my script doesn’t work not how to script a working one

Let me know if this code implements what you want

local Cam = workspace.CurrentCamera

while task.wait(0.01) do
	
	local LookVector = Cam.CFrame.LookVector
	local Part = script.Parent
	local Angle = math.atan(LookVector.Y / math.sqrt(LookVector.X ^ 2 + LookVector.Z ^ 2))
	Part.CFrame = CFrame.new(Part.Position) * CFrame.Angles(0,math.pi/2,-Angle)

end

I can explain it if it does

1 Like

It does work but whenever I put the angle in X or Z for some reason it always changes z instead
to give me this result


I tried on Y too but still doesn’t rotate in the correct axis
Your solution is close to what I want

local rs = game:GetService("RunService")
local cam = workspace.CurrentCamera
local part = script.Parent

while true do	rs.Stepped:Wait()
	local lv = cam.CFrame.LookVector
	local angle = math.atan2(lv.Y, math.sqrt(lv.X * lv.X + lv.Z * lv.Z))
	part.CFrame = CFrame.new(part.Position) * CFrame.Angles(0, math.pi/2, -angle)
end

I’ll explain it if this is what you want… if not there is really no reason.

You can try this, but if it doesn’t give you what you want you’ll need to play with it yourself to figure out what works

CFrame.Angles(math.pi / 2, Angle, 0)

I generally avoid using .Angles and alike functions because of the pain it is to figure out the proper rotation order and etc, so you’ll have to play around with the order and sign to figure out what rotation you want. Let me know if you need an explanation for anything

The problem with your current code

local Cam = workspace.Camera
local LookVector = script.Parent.CFrame.LookVector
local Part = script.Parent

while task.wait(0.01) do
local Angle = math.atan(LookVector.X / Cam.CFrame.LookVector.Y)
Part.CFrame = CFrame.new(Part.Position) * CFrame.Angles(0, math.pi/2, Angle)
end

  • You calculate Angle = math.atan(LookVector.X / Cam.CFrame.LookVector.Y). But:
  • LookVector.X is the X component of your part’s look vector.
  • Cam.CFrame.LookVector.Y is the Y component of the camera’s look vector.
  • But the Y component in Roblox LookVector is the vertical axis (up/down), not horizontal.
  • You’re mixing axes, so the angle calculated will not be the horizontal angle between them.
  • math.atan has a range limitation (returns values between -pi/2 and pi/2), so it can cause problems for full 360° rotations.
  • Also, math.atan(x/y) can fail or behave weirdly if y is 0.

I don’t need horizontal I need vertical
If math.atan has range limitation then how can I do the same thing with no limitations?

I have one more thing to say that the current code doesn’t rotate how it’s supposed to
It has like 60 or 90 degree limitation which makes me get confused on why

math.atan2 removes the ±90° limit … as posted in my script.

The script worked but the same thing wrong axis I played with the angles a bit
to reach what I want


local rs = game:GetService("RunService")
local cam = workspace.Camera
local part = script.Parent

while true do rs.Stepped:Wait()
	local lv = cam.CFrame.LookVector
	local angle = math.atan(lv.Y / math.sqrt(lv.X * lv.X + lv.Z * lv.Z))
	part.CFrame = CFrame.new(part.Position) * CFrame.Angles(-angle, 0, 0)
end

Can you now explain how this works?
I would really appreciate it if you told me why math.acos or math.asin doesn’t work here

We’re not there yet. Need to stumble a bit more, try this…

local rs = game:GetService("RunService")
local cam = workspace.CurrentCamera
local part = script.Parent

while true do rs.Stepped:Wait()
	local lv = cam.CFrame.LookVector
	local angle = math.atan2(lv.Z, lv.Y)
	part.CFrame = CFrame.new(part.Position) * CFrame.Angles(angle, math.pi/2, 0)
end

I tried this and what I see is that the part looks at where my camera is looking however not copying it’s current rotation just pointing where my camera is