How would I make this camera smooth?

Hello, I have used the help of a youtube video to make this script (It is a third person over the shoulder camera), it has helped a lot but i would like to make this camera move smoother. I do not understand Springs either.

local ReplicatedStorage = game:GetService("ReplicatedStorage") :: Service

local Knit = require(ReplicatedStorage.Packages.Knit)
local CameraController = Knit.CreateController { Name = "CameraController" }

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

local camera = workspace.CurrentCamera
local player = Players.LocalPlayer

local cameraOffset = Vector3.new(2, 2, 10)

function CameraController:KnitStart()
	
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")
		local rootPart = character:WaitForChild("HumanoidRootPart")
		
		local cameraAngleX = 0
		local cameraAngleY = 0
		
		
		humanoid.AutoRotate = false
		
		local function playerInput(actionName, inputState, inputObject)
			if inputState == Enum.UserInputState.Change then
				cameraAngleX -= inputObject.Delta.X
				cameraAngleY = math.clamp(cameraAngleY - inputObject.Delta.Y * 0.4, -75, 75)
			end
		end
		ContextActionService:BindAction("PlayerInput", playerInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)
		
		RunService:BindToRenderStep("CameraUpdate", Enum.RenderPriority.Camera.Value, function()
			local startCFrame = CFrame.new(rootPart.CFrame.Position) * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
			local cameraCFrame = startCFrame:PointToWorldSpace(cameraOffset)
			local cameraFocus = startCFrame:PointToWorldSpace(Vector3.new(cameraOffset.X, cameraOffset.Y, -100000))
			
			camera.CFrame = CFrame.lookAt(cameraCFrame, cameraFocus)
			
			local lookingCFrame = CFrame.lookAt(rootPart.Position, camera.CFrame:PointToWorldSpace(Vector3.new(0, 0, -100000)))
			
			rootPart.CFrame = CFrame.fromMatrix(rootPart.Position, lookingCFrame.XVector, rootPart.CFrame.YVector)
			
			local CameraRay = Ray.new(character.Head.Position, camera.CFrame.Position - character.Head.Position)
			local Ignore = {character}

			local HitPart, HitPosition = game.Workspace:FindPartOnRayWithIgnoreList(CameraRay, Ignore)

			camera.CFrame = (camera.CFrame - (camera.CFrame.Position - HitPosition)) + (character.Head.Position - camera.CFrame.Position).Unit
			
		end)
		
		
	end)
	
	local function focusControl(actionName, inputState, inputObject)
		if inputState == Enum.UserInputState.Begin then
			camera.CameraType = Enum.CameraType.Scriptable
			
			UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
			UserInputService.MouseIconEnabled = false --Optional for disabling mouse icon restart
			
			ContextActionService:UnbindAction("FocusControl")
		end
	end
	
	ContextActionService:BindAction("FocusControl", focusControl, false, Enum.UserInputType.MouseButton1, Enum.UserInputType.Touch, Enum.UserInputType.Focus)
	
	
	
end


return CameraController

Any help is appreciated! Sorry if the code is messy as well.

Use CFrame:Lerp(goalCFrame, alpha), it’s designed to smoothen CFrames by using interpolation. In other words, by having it not fully go to the goal CFrame.

On the line where they set the camera’s CFrame, change it to this:

-- old line: camera.CFrame = (camera.CFrame - (camera.CFrame.Position - HitPosition)) + (character.Head.Position - camera.CFrame.Position).Unit

-- new line:
local goalCFrame = (camera.CFrame - (camera.CFrame.Position - HitPosition)) + (character.Head.Position - camera.CFrame.Position).Unit
camera.CFrame = CFrame:Lerp(goalCFrame, alpha) 

alpha is a value between 0-1, which can be the looked at as the percentage of how complete it’ll go to goalCFrame. (hopefully that makes sense)

If you want to get a smooth effect, don’t set alpha to 1. (which will just have it go there fully completed)

Instead, look for in between numbers a little closer to 0 (0.35, 0.4, etc.). If you want to also consider the player’s FPS, because sometimes they could be lagging and the camera may not be following them as properly, then you’d instead multiply the deltaTime with any positive float.

-- fixed value for alpha:
alpha = 0.3
-- variable value influenced by renderStepped:
alpha = deltaTime * 18 -- roughly around 0.28-0.35 depending on your pc's refresh rate
-- if you want to also cap the alpha it to 60 fps, you can do this
alpha = deltaTime * 60 * / 3.5 -- between 0.24 to 0.31

If this helps you, then mark this as a solution for others to know. Apart from that, I hope you have a blessed day and good luck on your project! :D

1 Like

Thank you! With some editing this solution worked very well! I really appreciate it!

1 Like

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