Custom Camera Script Stuttering Bug

So i have this one camera script i ripped from the asset manager and am trying to implement a 3rd person 1st person support for it. It’s working, but i can’t seem to fix the stuttering issue.

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local human = character:WaitForChild("Humanoid")
local humanoidpart = character:WaitForChild("HumanoidRootPart")
local head = character:WaitForChild("Head")

local input = game:GetService("UserInputService")
local runService = game:GetService("RunService")

-- Settings
local Sensitivity = 0.6
local Smoothness = 0.05	
local HeadOffset = CFrame.new(0, 0.7, 0)

-- State
local CamPos, TargetCamPos = cam.CFrame.Position, cam.CFrame.Position 
local AngleX, TargetAngleX = 0, 0
local AngleY, TargetAngleY = 0, 0
local CanViewBody = true
local firstPersonEnabled = false

local function lerp(a, b, t)
	return a * (1 - t) + (b * t)
end

local function updateCharTransparency()
	for _, v in pairs(character:GetChildren()) do
		if v:IsA("BasePart") or v:IsA("UnionOperation") or v:IsA("MeshPart") then
			v.LocalTransparencyModifier = 1
			v.CanCollide = false
		elseif v:IsA("Accessory") or v:IsA("Hat") then
			if v:FindFirstChild("Handle") then
				v.Handle.LocalTransparencyModifier = 1
				v.Handle.CanCollide = false
			end
		end
	end
end

-- Run every frame
runService.RenderStepped:Connect(function()
	local camToHead = (cam.CFrame.Position - head.Position).Magnitude
	local isFirstPerson = cam.CameraType == Enum.CameraType.Custom and camToHead < 1

	if isFirstPerson then
		if not firstPersonEnabled then
			firstPersonEnabled = true
			updateCharTransparency()
		end

		CamPos = CamPos + (TargetCamPos - CamPos) * 0.28 
		AngleX = AngleX + (TargetAngleX - AngleX) * 0.35 
		local dist = TargetAngleY - AngleY 
		dist = math.abs(dist) > 180 and dist - (dist / math.abs(dist)) * 360 or dist 
		AngleY = (AngleY + dist * 0.35) % 360

		cam.CFrame = CFrame.new(head.Position)
			* CFrame.Angles(0, math.rad(AngleY), 0)
			* CFrame.Angles(math.rad(AngleX), 0, 0)
			* HeadOffset

		humanoidpart.CFrame = CFrame.new(humanoidpart.Position) * CFrame.Angles(0, math.rad(AngleY), 0)
	else
		firstPersonEnabled = false
	end
end)

input.InputChanged:Connect(function(inputObject)
	if not firstPersonEnabled then return end

	if inputObject.UserInputType == Enum.UserInputType.MouseMovement then
		local delta = Vector2.new(inputObject.Delta.x / Sensitivity, inputObject.Delta.y / Sensitivity) * Smoothness
		local X = TargetAngleX - delta.y 
		TargetAngleX = math.clamp(X, -80, 80)
		TargetAngleY = (TargetAngleY - delta.x) % 360 
	end	
end)

Any support is appreciated. I’m still trash when it comes to scripting.

1 Like

no need of function lerp
math.lerp already exists.
Also you most likely want to apply positions first there so
CFrame.new(head.Position)*HeadOffset and only then apply rotation

instead of RenderStepped, try one of these:
PreRender, PreAnimation, PreSimulation, PostSimulation

Add Heartbeat to the list.

1 Like