How can I make a camera follow a car smoothly?

I am currently trying to make a camera follow a car, but not follow it in a stiff manner (like setting the cameras CFrame to one thing strictly). So, I used tween service to achieve this and it did work, however the car looks really shakey when it moves in the perspective of the camera. Is there any way to prevent this?

Script:

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local camera = workspace.CurrentCamera
local setCamera = character:WaitForChild("Binds").SetCamera
local runService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local tweenService = game:GetService("TweenService")

local FIELD_OF_VIEW = 100
local ZOOMED_FIELD_OF_VIEW = 125

local connects = {}

local cameraPos
local frontCameraPos

function createCamera(willCreate, cameraPosition, frontCameraPosition)
	repeat wait()
		camera.CameraType = Enum.CameraType.Scriptable
	until camera.CameraType == Enum.CameraType.Scriptable
	
	if willCreate then
		cameraPos = cameraPosition
		frontCameraPos = frontCameraPosition
		camera.FieldOfView = FIELD_OF_VIEW
		camera.CFrame = cameraPos.CFrame
		connects.Run = runService.RenderStepped:Connect(cameraMovement)
		
		for _, boost in pairs(getSpeedBoosts()) do
			table.insert(connects, boost.Touched:Connect(speedBoost))
		end
	else
		repeat wait()
			camera.CameraType = Enum.CameraType.Custom
		until camera.CameraType == Enum.CameraType.Custom
		
		for _, connect in pairs(connects) do
			connect:Disconnect()
		end
		
		cameraPos = nil
		frontCameraPos = nil
	end
end

function tweenToCam(toCFrame)
	local tweenInfo = TweenInfo.new(
		0.03,
		Enum.EasingStyle.Linear,
		Enum.EasingDirection.InOut,
		0,
		false
	)
	
	local properties = {
		CFrame = toCFrame
	}
	
	local tween = tweenService:Create(camera, tweenInfo, properties)
	
	tween:Play()
	
	tween.Completed:Connect(function()
		tween:Pause()
	end)
end

function cameraMovement()
	if cameraPos and frontCameraPos then
		if UIS:IsKeyDown(Enum.KeyCode.LeftShift) then
			camera.CFrame = frontCameraPos.CFrame
		else
			tweenToCam(cameraPos.CFrame)
		end
	end
end

function speedBoost()
	local tweenInfo = TweenInfo.new(
		0.25, 
		Enum.EasingStyle.Linear, 
		Enum.EasingDirection.InOut,
		0,
		false
	)
	
	local properties = {
		FieldOfView = ZOOMED_FIELD_OF_VIEW
	}
	
	local properties2 = {
		FieldOfView = FIELD_OF_VIEW
	}
	
	local tween = tweenService:Create(camera, tweenInfo, properties)
	local tween2 = tweenService:Create(camera, tweenInfo, properties2)
	
	tween:Play()
	wait(1.5)
	tween2:Play()
end

function getSpeedBoosts()
	local boosts = {}

	for _, part in pairs(workspace:GetDescendants()) do
		if part.Name == "Speed" then
			table.insert(boosts, part)
		end
	end

	return boosts
end

setCamera.Event:Connect(createCamera)
2 Likes

What I do is put a part and then make it the camera’s subject and then just make the part follow behind the car, lagging behind slightly so that it produces the desired effect. You might wanna use bodyposition or something.

Here’s a video of one of my old projects using this

3 Likes

Do I set the camera’s focus to the part as well, or do I leave the camera’s focus unchanged?

idk what you mean by focus but I have it locked onto the part, like how it’s locked onto the character’s head by default.

this is my script for the camera

local CameraPart = Instance.new("Part", Head)

local Camera = game.Workspace.Camera

CameraPart.CanCollide = false

CameraPart.Transparency = 1

CameraPart.Anchored = false

Camera.CameraSubject = CameraPart

local CameraVel = Instance.new("BodyPosition", CameraPart)

CameraVel.Position = HRP.Position + Vector3.new(0, 1.5, 0)

CameraVel.D = 500

CameraVel.MaxForce = Vector3.new(10000, 10000, 10000)
5 Likes