CFrame.Angles makes my character spin

Hello devs! So I’m working on custom first person camera system, here’s the code :

Code
repeat task.wait() until game:IsLoaded()

local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")
local context = game:GetService("ContextActionService")
local ts = game:GetService("TweenService")

local plr = game.Players.LocalPlayer

local cam = workspace.CurrentCamera

local mouse = plr:GetMouse()

local xAngle = 0
local yAngle = 0
local cameraPos = Vector3.new(0,0,0) --0,0,8.5

local camCF = CFrame.new()
local camRotation = CFrame.Angles(0,0,0)
local camRotationOffset = CFrame.Angles(0,0,0)

cam.CameraType = Enum.CameraType.Scriptable

context:BindAction("CameraMovement",function(_,_,input)
	xAngle = xAngle - input.Delta.X * 0.4
	yAngle = math.clamp(yAngle - input.Delta.Y * 0.4,-80,80)
end, false, Enum.UserInputType.MouseMovement)

rs.RenderStepped:Connect(function()
	if plr.Character then
		local rootPart = plr.Character:FindFirstChild("HumanoidRootPart")
		local head = plr.Character:FindFirstChild("Head")
		local hum = plr.Character:FindFirstChildWhichIsA("Humanoid")
		if rootPart and head and hum and hum.Health > 0 then
			if hum.MoveDirection.Magnitude > 0 then
				local velo = hum.RootPart.Velocity
				local cos = math.abs(math.cos(tick() * 9)) / 5
				local sin = math.sin(tick() * 12) / 2
				hum.CameraOffset = hum.CameraOffset:Lerp(Vector3.new(0,cos,0) * math.min(1,velo.Magnitude / hum.WalkSpeed),0.25)
				local sinFix = sin * math.min(1,velo.Magnitude / hum.WalkSpeed)
				camRotationOffset = CFrame.Angles(math.rad(sinFix),math.rad(sinFix),math.rad(sinFix))
			else
				hum.CameraOffset = hum.CameraOffset * 0.75
				camRotationOffset = CFrame.Angles(math.rad(0),math.rad(0),math.rad(0))
			end
			workspace.CurrentCamera.CFrame = camCF * camRotation
			local startCF = CFrame.new((rootPart.CFrame.Position + Vector3.new(0,2,0))) * CFrame.Angles(0,math.rad(xAngle),0) * CFrame.Angles(math.rad(yAngle),0,0)
			local cameraCFrame = startCF + startCF:VectorToWorldSpace(Vector3.new(cameraPos.X,cameraPos.Y,cameraPos.Z))
			local cameraFocus = startCF + startCF:VectorToWorldSpace(Vector3.new(cameraPos.X,cameraPos.Y,-50000))
			local lookat = CFrame.lookAt(cameraCFrame.Position,cameraFocus.Position)
			camCF = CFrame.new(lookat.X,lookat.Y,lookat.Z) * CFrame.new(hum.CameraOffset)
			camRotation = camRotation:Lerp(lookat.Rotation * camRotationOffset,0.3)
			uis.MouseBehavior = Enum.MouseBehavior.LockCenter
			rootPart.CFrame = CFrame.new(rootPart.Position) * CFrame.Angles(0,math.rad(xAngle),0)
			
			for _,i in pairs(plr.Character:GetDescendants()) do
				if i:IsA("BasePart") then
					if i.LocalTransparencyModifier < 0.9 then
						i.LocalTransparencyModifier = 1
					end
				end
			end
		end
	end
end)

And this is footage of the system and of the spinning :

Video

1 Like

You are most certainly overcomplicating it.

I would simply do this in order to align the character with the camera’s look direction:

local rotationX, rotationY, rotationZ = camera.CFrame:ToOrientation()
rootPart.CFrame = CFrame.new(rootPart.Position) * CFrame.fromOrientation(0, rotationY, 0)
local run = game:GetService("RunService")
local players = game:GetService("Players")
local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:WaitForChild("HumanoidRootPart")

local camera = workspace.CurrentCamera

run.RenderStepped:Connect(function()
	hrp.CFrame = CFrame.lookAt(hrp.Position, camera.CFrame.Position) * CFrame.Angles(0, math.pi, 0)
end)

I didn’t request full code but okay.

That didn’t work. My character still spins.

It does work in an empty baseplate place. You must’ve implemented it incorrectly.

I implemented it exactly like you did, but I replaced fromOrientation to Angles because it feels ancient for me.

You can’t just choose which method to use, .fromOrientation is not equivalent to .Angles, however this is probably not the issue.

After trying your code in an empty baseplate place, the “spinning” doesn’t happen. Which means the script is not what’s causing the “spinning” issue.

The code is placed in StarterPlayerScripts.

This works & you can omit the Y-axis if you’d like.

I placed the script into StarterCharacterScripts and it magically fixed the bug.