Lerping camera results in weird behaviour while turning

I am trying to create a camera system which has weight on both moving and rotating. This means that the camera is slightly delayed when either looking around or walking. What I am trying to use to accomplish this is to lerp the camera’s cframe.

While this method does work for the movement delay, trying to look around makes the player go off centre, and if the camera is moved too fast, it just bounces back around.


I don’t really know why it does this, as I have also had this issue in the past where the character goes off centre.

local CAS = game:GetService("ContextActionService")
local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")

local plr = game.Players.LocalPlayer
local cam = game.Workspace.Camera
local camOffset = Vector3.new(0, 4, 20)

local weight = 10

	local hum = chr:WaitForChild("Humanoid")
	local root = chr:WaitForChild("HumanoidRootPart")
	local head = chr:WaitForChild("Head")
	root.CFrame = spawnpoint.CFrame * CFrame.new(0, 2, 0)
	local camAngX = 0
	local camAngY = 0
	local function plrInput(_, inpState, inpObject)
		if inpState == Enum.UserInputState.Change then
			camAngX = camAngX - inpObject.Delta.X
			camAngY = math.clamp(camAngY - inpObject.Delta.Y * 0.2, -35, -35)		

	CAS:BindAction("plrInput", plrInput, false, Enum.UserInputType.MouseMovement)
		if cam.CameraType ~= Enum.CameraType.Scriptable then
			cam.CameraType = Enum.CameraType.Scriptable

		local startCF = CFrame.new(head.CFrame.Position) * CFrame.Angles(0, math.rad(camAngX), 0) * CFrame.Angles(math.rad(camAngY), 0, 0)
		local camCFrame = startCF:ToWorldSpace(CFrame.new(camOffset.X, camOffset.Y, camOffset.Z))
		local camFocus = startCF:ToWorldSpace(CFrame.new(camOffset.X, camOffset.Y, -10000))

		local org = head.Position
		local dir = CFrame.lookAt(head.Position, camCFrame.Position).LookVector * 15

		local params = RaycastParams.new()
		params.FilterType = Enum.RaycastFilterType.Blacklist
		params.FilterDescendantsInstances = {chr, workspace["clipThrough"]}

		local hitPos

		local result = workspace:Raycast(org, dir, params)

		if result then
			hitPos = result.Position
			hitPos = org + dir

		cam.CFrame = cam.CFrame:Lerp(CFrame.lookAt(hitPos, camFocus.Position), 1 / weight)