Problems with Locking Camera to Constant Position Relative to Character Model

I’m building a Camera Controller reminiscent of the Shiftlock camera (with minor changes.) One of these mechanics reminiscent of Shiftlock is keeping the Camera focused, at all times, behind and to the right of the player, despite any rotation of the player and / or camera.

Here, you can view the problem in action. The Camera’s focus seems to shift depending on my Camera’s orientation.

Here you can find the intended result. This is simply ROBLOX’s default Shiftlock mode.

Below you can find the code relevant to this issue.

local currentCamera = workspace.CurrentCamera
local mouse = game.Players.LocalPlayer:GetMouse()
local character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local rootPart = character:WaitForChild("HumanoidRootPart")
local playerPosition = rootPart.Position

local standardCameraPosition = rootPart.Position + Vector3.new(5, 2.25, 0)
local standardCameraRotation = Vector2.new(0, math.rad(-60))
local standardCameraZoom = 10

local cameraPosition = standardCameraPosition
local cameraRotation = standardCameraRotation
local cameraZoom = standardCameraZoom

local cameraRotationBounds = {math.rad(-81), math.rad(20)}
local cameraZoomBounds = nil
local cameraSpeed = 0.1
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25

local function cameraModeHandler()
	currentCamera.CameraType = Enum.CameraType.Scriptable
	currentCamera.CameraSubject = nil
end

cameraModeHandler()

local function updateCameraProperties()
	local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
	currentCamera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame*Vector3.new(0, 0, cameraZoom)
	currentCamera.Focus = currentCamera.CFrame - Vector3.new(0, currentCamera.CFrame.p.Y, 0)
end

game:GetService("UserInputService").InputBegan:Connect(function(inputObject)
	if inputObject.KeyCode == Enum.KeyCode.I then
		cameraZoom = cameraZoom - 5
	elseif inputObject.KeyCode == Enum.KeyCode.O then
		cameraZoom = cameraZoom + 5
	end
	
	if cameraZoomBounds ~= nil then
		cameraZoom = math.min(cameraZoom, cameraZoomBounds[1], cameraZoomBounds[2])
	else
		cameraZoom = math.max(cameraZoom, 0)
	end
	
	updateCameraProperties()
end)

mouse.Move:Connect(function()
	local deltaRotation = game:GetService("UserInputService"):GetMouseDelta() * Vector2.new(-1, -1)
	
	cameraRotation = cameraRotation + deltaRotation*math.rad(cameraMouseRotateSpeed)
end)

local function runServiceBound()
	local movement = rootPart.Position - playerPosition
	
	game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
	
	local cameraLookVector = currentCamera.CFrame.LookVector
	local readFromRotation = math.atan2(-cameraLookVector.X, -cameraLookVector.Z)
	rootPart.CFrame = CFrame.new(rootPart.Position) * CFrame.Angles(0, readFromRotation, 0)
	
	cameraPosition = cameraPosition + movement
	playerPosition = rootPart.Position
	
	updateCameraProperties()
end

game:GetService("RunService"):BindToRenderStep("BoundedFunction", Enum.RenderPriority.Camera.Value-1, runServiceBound)

Specifically, the problem seems to rest in runServiceBound() and updateCameraProperties. The following excerpt of code (found in runServiceBound()) is my current solution:

local cameraLookVector = currentCamera.CFrame.LookVector
local readFromRotation = math.atan2(-cameraLookVector.X, -cameraLookVector.Z)
rootPart.CFrame = CFrame.new(rootPart.Position) * CFrame.Angles(0, readFromRotation, 0)

This process achieves only a portion of what I desire, as it keeps the Character model consistently facing forwards, however the Camera fails to consistently stay behind and to the right of the Character’s model, the other half of what I need.
Any ideas?

Fixed. Specifically adjusted this line

currentCamera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame*Vector3.new(0, 0, cameraZoom)

To become this line:

currentCamera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame*Vector3.new(5, 2.25, cameraZoom)

Essentially, I multiplied my offset to the Camera’s CFrame over adding it.