Making a player's character turn in the direction the camera is facing

I’m attempting to make an over-shoulder camera system that, upon equipping a tool, will forcibly orient their character’s root part in the direction the player’s camera is facing. While I have the OTS camera logic working (sort of), I’m getting an odd effect when the player does equip a tool.

I’ve tried using the following code, with varying results. The most common result, however, is that the player’s character either is side-on to the camera, or is facing towards it, instead of what I’m trying to go for. It’s incredibly inconsistent.

The script (collapsed for convenience)

Note: this script is (obviously) unfinished, there’s still some optimizations to do

-- Services
local RunService = game:GetService("RunService")
local PlrService = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")
local UserInputService = game:GetService("UserInputService")

-- Primary Values
local Player = PlrService.LocalPlayer
local MyHumanoid:Humanoid = nil
local MyRootPart:BasePart = nil

-- Secondary Values
local CurrentCamera = workspace.CurrentCamera
local CameraOffset = Vector3.new(1.65, 1.8, 4.7)
local CameraAngleX = 0
local CameraAngleY = 0
local ToolCounter = 0
local HasTool = false

-- Functions
function Refocus(actionName, inputState, inputObject)
	-- Lock and hide mouse icon on input began
	if inputState == Enum.UserInputState.Begin and HasTool == true and ToolCounter > 0 then
		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	end
end

function ItemAdded(NewItem:Instance)
	-- Enable OTS camera mode if player is holding tools
	if NewItem:IsA("Tool") then
		ToolCounter += 1
		if HasTool == false and ToolCounter > 0 then
			HasTool = true
			MyRootPart.CFrame = CFrame.lookAt(MyRootPart.Position,MyRootPart.Position+CurrentCamera.CFrame.LookVector)
			while CurrentCamera.CameraType ~= Enum.CameraType.Scriptable do
				CurrentCamera.CameraType = Enum.CameraType.Scriptable
			end
			UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
			MyHumanoid.AutoRotate = false
		end
	end
end

function ItemRemoved(OldItem:Instance)
	-- Disable OTS camera mode if player is no longer holding tools
	if OldItem:IsA("Tool") then
		ToolCounter -= 1
		wait()
		if ToolCounter <= 0 then
			HasTool = false
			while CurrentCamera.CameraType ~= Enum.CameraType.Custom do
				CurrentCamera.CameraType = Enum.CameraType.Custom
			end
			UserInputService.MouseBehavior = Enum.MouseBehavior.Default
			MyHumanoid.AutoRotate = true
		end
	end
end

function CharacterAdded(NewCharacter:Model)
	MyHumanoid = NewCharacter:WaitForChild("Humanoid")
	MyRootPart = NewCharacter:WaitForChild("HumanoidRootPart")
	
	CameraAngleX = 0
	CameraAngleY = 0

	local function playerInput(actionName, inputState, inputObject)
		-- Calculate camera/player rotation on input change
		if inputState == Enum.UserInputState.Change then
			CameraAngleX = CameraAngleX - inputObject.Delta.X
			-- Reduce vertical mouse/touch sensitivity and clamp vertical axis
			CameraAngleY = math.clamp(CameraAngleY-inputObject.Delta.Y*0.4, -75, 75)
			if HasTool == true and CurrentCamera.CameraType == Enum.CameraType.Scriptable then
				-- Rotate root part CFrame by X delta
				MyRootPart.CFrame = MyRootPart.CFrame * CFrame.Angles(0, math.rad(-inputObject.Delta.X), 0)
			end
		end
	end
	ContextActionService:BindAction("PlayerInput", playerInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)

	RunService.RenderStepped:Connect(function()
		if HasTool == false or CurrentCamera.CameraType ~= Enum.CameraType.Scriptable then return false end

		local startCFrame = CFrame.new((MyRootPart.CFrame.Position)) * CFrame.Angles(0, math.rad(CameraAngleX), 0) * CFrame.Angles(math.rad(CameraAngleY), 0, 0)
		local cameraCFrame = startCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, CameraOffset.Z))
		local cameraFocus = startCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, -10000))
		CurrentCamera.CFrame = CFrame.new(cameraCFrame.Position, cameraFocus.Position)
	end)

	NewCharacter.ChildAdded:Connect(ItemAdded)
	NewCharacter.ChildRemoved:Connect(ItemRemoved)
end

-- Primary Connections
Player.CharacterAdded:Connect(CharacterAdded)
ContextActionService:BindAction("FocusControl", Refocus, false, Enum.UserInputType.Focus)

Anyone have some pointers for how to accomplish this task properly? I’ve tried using Camera:ViewportPointToRay() as well with no desired results there either.

EDIT: Changed some Lua comments on the script because I noticed typos in them here and there. The script itself remains functionally the same.

Use the “CameraType” in camera. not sure what you adjust it to, but change it from “Fixed” to one of the other options and test it out

In a local script:

game.workspace.CurrentCamera.CameraType = "Track"

Not sure if it is track or one of the other options tho

I’m using the Scriptable camera type, since as I said before I’m trying to make an OTS camera system that activates whenever the player is holding a tool.

Thanks for trying to help though, I do appreciate it.

EDIT: Also, when the player isn’t holding a tool, the camera would be set to Enum.CameraType.Custom (the default behavior).