Console Controller - Custom Camera Bug

Hi, attached is a video of whats wrong with my custom camera system. I’m trying to implement support for console controllers (as you can see in the code) it sorta works but it can be really ‘slurred’ sometimes. In the provided video, you’ll see that instead of smoothly rotating around the player, the camera gets ‘slurred’ / ‘sorta gittery’

here is my code (a module script)

local module = {}

local uis = game:GetService("UserInputService")
local camera = workspace.CurrentCamera
local TS = game:GetService("TweenService")
local RUN_SERVICE = game:GetService("RunService")
local Player = game:GetService("Players").LocalPlayer
local Mouse = Player:GetMouse()

local Character
local HRP

local IsMouseHidden = false
local IsMouseLocked = false
local Enabled = false
local CameraState = "TPS"

local x, y = 0, 0
local Offset = Vector3.new(0, 2, 10)
local sensitivity = 0.15
local ObstructionExclusions = {}
local lerpSpeed = 1

function _MainLoop()
	if IsMouseLocked == true then
		uis.MouseBehavior = Enum.MouseBehavior.LockCenter
	elseif IsMouseLocked == false then
		uis.MouseBehavior = Enum.MouseBehavior.Default
	end

	uis.MouseIconEnabled = not IsMouseHidden
	
	if CameraState == "TPS" then
		TPS_CAMERA()
	elseif CameraState == "Obstruction_Dynamic" or CameraState == "Od" then
		
	end
end

module.MainLoop = function(toggle)
	Enabled = toggle
	if toggle == true then
		camera.CameraType = Enum.CameraType.Scriptable
		RUN_SERVICE:BindToRenderStep("CameraSystemLoop", Enum.RenderPriority.Camera.Value, _MainLoop)
	else
		RUN_SERVICE:UnbindFromRenderStep("CameraSystemLoop")
		camera.CameraType = Enum.CameraType.Custom
	end
end

module.SetFOV = function(newFOV, t)
	if t ~= nil then
		local tween = TS:Create(camera, TweenInfo.new(t), {FieldOfView = newFOV})
		tween:Play()
	else
		camera.FieldOfView = newFOV
	end
end

module.ConnectPlayer = function(char)
	Character = char
	HRP = Character:WaitForChild("HumanoidRootPart")
end

module.SetObstructionExclusions = function(exclusions)
	ObstructionExclusions = exclusions
end

module.SetCameraState = function(state)
	CameraState = state
end

module.SetMouseLocked = function(locked)
	IsMouseLocked = locked
end

module.SetMouseHidden = function(hidden)
	IsMouseHidden = hidden
end


function tps_look(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		x = x - input.Delta.X * sensitivity
		y = math.clamp(y - input.Delta.Y * sensitivity * .8, -75, 75)
	elseif input.KeyCode == Enum.KeyCode.Thumbstick2 then
		local deadzone = 0.1
		if math.abs(input.Position.X) > deadzone or math.abs(input.Position.Y) > deadzone then
			x = x - input.Position.X * sensitivity * 1.7
			y = math.clamp(y + input.Position.Y * sensitivity * 1.7, -75, 75)
		end
	end
end

uis.InputChanged:Connect(function(input, processed)
	if processed then return end
	if Enabled then
		if input.UserInputType == Enum.UserInputType.MouseMovement or input.KeyCode == Enum.KeyCode.Thumbstick2 then
			tps_look(input)
		end
	end
end)


function lerp(a, b, alpha)
	return a:Lerp(b, alpha)
end

function TPS_CAMERA()
	if HRP then
		local currentCFrame = camera.CFrame
		local targetCFrame
		local startCFrame

		startCFrame = CFrame.new(HRP.Position) * CFrame.Angles(0, math.rad(x), 0) * CFrame.Angles(math.rad(y), 0, 0)

		local cameraCFrame = startCFrame:ToWorldSpace(CFrame.new(Offset.X, Offset.Y, Offset.Z))
		local cameraDirection = startCFrame:ToWorldSpace(CFrame.new(Offset.X, Offset.Y, -10000))

		-- Raycasting for Obstruction Displacement
		local rayOrigin = HRP.Position
		local rayDirection = (cameraCFrame.Position - rayOrigin).Unit * 20
		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = ObstructionExclusions
		raycastParams.FilterType = Enum.RaycastFilterType.Exclude
		raycastParams.IgnoreWater = true

		local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
		if raycastResult then
			local obstructedPosition = raycastResult.Position
			cameraCFrame = CFrame.new(obstructedPosition + (raycastResult.Normal * 0.5), rayOrigin)
		end

		targetCFrame = CFrame.new(cameraCFrame.Position, cameraDirection.Position)

		camera.CFrame = lerp(currentCFrame, targetCFrame, lerpSpeed)
	end
end

return module

If you could help, that’d be great thanks. Btw, chat gpt was no use, after an hour of bugging it to help me.