Getting Degrees Camera Has Pivoted Around Character

Trying to get the rotation a camera has spin around the character like this:

0 degrees:
image

15 degrees:
image

if your goal is to get the number of degrees the camera has rotated, your best bet would be to do something like this:

get a table of desired rotations that range from 0 to 360, increment by 15

local rotations = {}
for i = 0, 360, 15 do
	table.insert(rotations, i)
end

then normalize the angle to compare it easier

function normalize(angle)
	angle %= 360
	if angle > 180 then
		angle -= 360
	end
	return angle
end

afterward, take the dot product of the camera’s right vector and the left (negative right) vector of the character’s root (camRight:Dot(mainPartOrientation)) to determine how much one vector aligns with another

then you can take this dot product and convert it to an angle (in radians)
(i’m using deg here to make it a tad bit more intuitive)

local rawAngle = math.deg(math.acos(camRight:Dot(mainPartOrientation)))
local angle = normalize(rawAngle)

then you could use the cross product of the two vectors (camRight and mainPartOrientation) to determine the relative direction of the angle

local crossProduct = camRight:Cross(mainPartOrientation)
if crossProduct.Y < 0 then
	angle = -angle
end

afterward, you can find the closest predefined rotation

for _, rotation in rotations do
	local difference = math.abs(normalize(rotation) - angle)
	if difference < minDifference then
		minDifference = difference
		closestRotation = rotation
	end
end

the full script, in case my explanation was kinda crappy

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local currentCam = workspace.CurrentCamera

-- safe character retrieval
local function getCharacter()
	local character = player.Character
	return if character and character.Parent then character else player.CharacterAdded:Wait()
end

local char = getCharacter()
local mainPart = char:WaitForChild("HumanoidRootPart")

-- 15-degree rotations from 0 to 360
local rotations = {}
for i = 0, 360, 15 do
	table.insert(rotations, i)
end

-- wrap an angle within 0 to 360 degrees & convert any angle greater than 180 to its negative counterpart
function normalize(angle)
	angle %= 360
	if angle > 180 then
		angle -= 360
	end
	return angle
end

RunService.RenderStepped:Connect(function()
	local camRight = currentCam.CFrame.RightVector
	local mainPartOrientation = -(mainPart.CFrame.RightVector)

	-- calculate the angle between the camera and the main part
	local rawAngle = math.deg(math.acos(camRight:Dot(mainPartOrientation)))
	local minDifference = math.huge
	local angle = normalize(rawAngle)
	local closestRotation = nil

	-- adjust angle based on cross product's y-axis
	local crossProduct = camRight:Cross(mainPartOrientation)
	if crossProduct.Y < 0 then
		angle = -angle
	end

	for _, rotation in rotations do -- find closest predefined rotation
		local difference = math.abs(normalize(rotation) - angle)
		if difference < minDifference then
			minDifference = difference
			closestRotation = rotation
		end
	end

	-- based on the closest rotation, now you can do things
	player:SetAttribute("angle", closestRotation) -- this is an example !!
end)

good luck with ur development
fumo

Thanks, I’ll try this tomorrow, 15 degrees was just an example, so you didn’t need to make the normalize function, but thank you!

1 Like

Your code seems to restrict the angle to a certain rotation for some reason, and then it resets back, possibly because you’re using :Dot() which I am not familiar with, but this is what I used instead, thanks though.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.