Third Person Camera Glitching

I am making a third person, over the shoulder, camera for my game, but how my script is rotating the character is pretty buggy.


As you can see and if you try the code out yourself, the character is glitching out when moving in different directions and rotating around, especially when you move backwards.

I want the camera and character to be more smooth and prevent this laggy type of movement.

Here is my code:

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")

local connection = nil
local enabled = false

local player = Players.LocalPlayer

local character = player.Character or player.CharacterAdded:Wait()
local camera = workspace.CurrentCamera

local root = character.PrimaryPart

local function RotateCharacter()

	local lookVector = camera.CFrame.LookVector
	local flatVector = Vector3.new(lookVector.X, 0, lookVector.Z).Unit
	
	local targetCFrame = CFrame.new(root.Position, root.Position + flatVector)
	
	root.CFrame = targetCFrame
end

local tweenInfo = TweenInfo.new(0.2, Enum.EasingStyle.Quint, Enum.EasingDirection.Out)

local function TweenOffset(bool)
	
	if bool then

		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter

		local tween = TweenService:Create(character.Humanoid, tweenInfo, {CameraOffset = Vector3.new(2, 0.25, 0)})
		tween:Play()
		
		if connection then connection:Disconnect() end 
		
		connection = RunService.PreRender:Connect(function()
			
			RotateCharacter()
		end)
	else
		
		UserInputService.MouseBehavior = Enum.MouseBehavior.Default

		local tween = TweenService:Create(character.Humanoid, tweenInfo, {CameraOffset = Vector3.new(0, 0, 0)})
		tween:Play()

		if connection then connection:Disconnect() end 
	end
end

UserInputService.InputBegan:Connect(function(input, processed)
	
	if processed then return end

	if input.KeyCode == Enum.KeyCode.Z then
		
		enabled = not enabled
		
		TweenOffset(enabled)
	end
end)
2 Likes

I faced this exact same problem a while back. It took me 3 years to figure out a solution. Here’s the code. It includes obstruction detection, so the camera moves forward in front of a part and not right through it!

function CameraController:EnableThirdPerson()
	if os.time() - self.TimeSinceDeactivation < 1 then
		task.cancel(self.DeactivationTask)
		self.DeactivationTask = nil
	end
	
	local Character: Model = self.Player.Character or self.Player.CharacterAdded:Wait()
	local Humanoid: Humanoid = Character:WaitForChild("Humanoid")
	local HumanoidRootPart: BasePart = Character:WaitForChild("HumanoidRootPart")
	
	self.LerpTo = self.RightCameraOffset
	
	Camera.CameraType = Enum.CameraType.Scriptable
	UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	UserInputService.MouseIconEnabled = false
	
	RunService:BindToRenderStep(self.ThirdPersonRender, Enum.RenderPriority.Camera.Value, function(DeltaTime)
		self.GlobalCameraOffset = self.GlobalCameraOffset:Lerp(self.LerpTo, 0.1)
		
		local StartCFrame = CFrame.new(HumanoidRootPart.CFrame.Position) * CFrame.Angles(0, math.rad(self.CameraAngleX), 0) * CFrame.Angles(math.rad(self.CameraAngleY), 0, 0)
		local CameraCFrame = StartCFrame:PointToWorldSpace(self.GlobalCameraOffset)
		local CameraFocus = StartCFrame:PointToWorldSpace(Vector3.new(self.GlobalCameraOffset.X, self.GlobalCameraOffset.Y, -1000000))
		
		UserInputService.MouseDeltaSensitivity = 0.5
		
		Camera.CFrame = CFrame.lookAt(CameraCFrame, CameraFocus)
		
		local LookCFrame = CFrame.lookAt(HumanoidRootPart.Position, Camera.CFrame:PointToWorldSpace(Vector3.new(0, 0, -1000000)))
		HumanoidRootPart.CFrame = HumanoidRootPart.CFrame:Lerp(CFrame.fromMatrix(HumanoidRootPart.Position, LookCFrame.XVector, HumanoidRootPart.CFrame.YVector), 0.1)
		Humanoid.AutoRotate = false 
		
		local RaycastParameters = RaycastParams.new()
		RaycastParameters.FilterType = Enum.RaycastFilterType.Exclude
		RaycastParameters.FilterDescendantsInstances = {Character}
		
		local RaycastResult = workspace:Raycast(Character.Head.Position, Camera.CFrame.Position - Character.Head.Position, RaycastParameters)
		
		if RaycastResult then
			local HitPart, HitPosition = RaycastResult.Instance, RaycastResult.Position
			Camera.CFrame = (Camera.CFrame - (Camera.CFrame.Position - HitPosition)) + (Character.Head.Position - Camera.CFrame.Position).Unit
		end
	end)
end
1 Like

I fixed the problem. Make sure to set humanoid.AutoRotate = false. :man_facepalming:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.