Issue with Third Person Shoulder Camera

  1. What do you want to achieve? Keep it simple and clear!
    I want help in finding a solution to my problem.
  2. What is the problem? Include screenshots/videos if possible.
    I made a third person shoulder camera system for my project. It works fine, but there’s a big problem, when facing the camera or any direction that’s not forward, it rotates the camera based on the HumanoidRootPart CFrame. This causes the camera to sometimes turn 180*.
    Here is a video of the problem occurring: Watch issue | Streamable
  3. What solutions have you tried so far?
    ChatGPT, Claude.ai, x.ai, reading the forum posts, nothing seems to work.
local uis = game:GetService("UserInputService")
local camera = workspace.CurrentCamera
local char = script.Parent
local humanoid = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")
local runService = game:GetService("RunService")

local x = 0
local y = 0
local offset = Vector3.new(2.5, 2.1, 7)
local isActive = false
local canZoom = false
local defaultCameraType = camera.CameraType
local defaultAutoRotate = humanoid.AutoRotate
local minZoom = 2
local maxZoom = 20
local lastCameraRotation = CFrame.identity

local cameraLerpAlpha = 0
local cameraLerpSpeed = 5
local transitioningToCamera = false
local transitioningToDefault = false
local deactivationLerpAlpha = 0
local defaultCameraOffset

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

local function enableCameraControl()
    local hrpCFrame = hrp.CFrame
    local cameraCFrame = camera.CFrame
    defaultCameraOffset = hrpCFrame:ToObjectSpace(cameraCFrame)

    isActive = true
    transitioningToCamera = true
    transitioningToDefault = false
    cameraLerpAlpha = 0

    local _, currentY, _ = camera.CFrame:ToOrientation()
    x = math.deg(currentY)
    lastCameraRotation = CFrame.Angles(0, math.rad(x), 0) * CFrame.Angles(math.rad(y), 0, 0)

    camera.CameraType = Enum.CameraType.Scriptable
    humanoid.AutoRotate = false
    uis.MouseBehavior = Enum.MouseBehavior.LockCenter
end

local function disableCameraControl()
    isActive = false
    transitioningToCamera = false
    transitioningToDefault = true
    deactivationLerpAlpha = 0
end

local function adjustCameraForCollisions(targetPosition, lookTarget)
    local rayOrigin = hrp.Position
    local rayDirection = targetPosition - rayOrigin
    local rayLength = rayDirection.Magnitude
    local rayUnit = rayDirection.Unit
    local rayDistance = math.min(rayLength, maxZoom)

    local ignoreList = {char}
    local raycastParams = RaycastParams.new()
    raycastParams.FilterDescendantsInstances = ignoreList
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude

    local raycastResult = workspace:Raycast(rayOrigin, rayUnit * rayDistance, raycastParams)

    if raycastResult then
        local hitPoint = raycastResult.Position
        local wallOffset = 0.5
        local adjustedPosition = hitPoint - (rayUnit * wallOffset)
        local distanceToCharacter = (adjustedPosition - rayOrigin).Magnitude
        if distanceToCharacter < minZoom then
            adjustedPosition = rayOrigin + rayUnit * minZoom
        end
        return CFrame.new(adjustedPosition, lookTarget)
    else
        return CFrame.new(targetPosition, lookTarget)
    end
end

uis.InputBegan:Connect(function(input, processed)
    if processed then return end
    if input.UserInputType == Enum.UserInputType.MouseButton2 then
        enableCameraControl()
    end
end)

uis.InputEnded:Connect(function(input, processed)
    if processed then return end
    if input.UserInputType == Enum.UserInputType.MouseButton2 then
        disableCameraControl()
    end
end)

uis.InputChanged:Connect(function(input, processed)
    if input.UserInputType == Enum.UserInputType.MouseWheel and isActive and canZoom then
        offset = Vector3.new(
            offset.X,
            offset.Y,
            math.clamp(offset.Z - input.Position.Z * 2, minZoom, maxZoom)
        )
    end

    if processed then return end
    if input.UserInputType == Enum.UserInputType.MouseMovement and isActive then
        x -= input.Delta.X
        y = math.clamp(y - input.Delta.Y * 0.4, -75, 75)
        lastCameraRotation = CFrame.Angles(0, math.rad(x), 0) * CFrame.Angles(math.rad(y), 0, 0)
    end
end)

local renderConnection = runService.RenderStepped:Connect(function(dt)
    dt = math.min(dt, 0.1)

    if isActive then
        if humanoid.AutoRotate then
            humanoid.AutoRotate = false
        end

        local currentCFrame = hrp.CFrame
        hrp.CFrame = CFrame.new(currentCFrame.Position) * CFrame.Angles(0, math.rad(x), 0)

        local startCFrame = CFrame.new(hrp.Position) * lastCameraRotation
        local cameraCFrame = startCFrame:ToWorldSpace(CFrame.new(offset.X, offset.Y, offset.Z))
        local cameraDirection = startCFrame:ToWorldSpace(CFrame.new(offset.X, offset.Y, -10000))

        local adjustedCameraCFrame = adjustCameraForCollisions(cameraCFrame.Position, cameraDirection.Position)

        if transitioningToCamera then
            cameraLerpAlpha = math.clamp(cameraLerpAlpha + dt * cameraLerpSpeed, 0, 1)
            camera.CFrame = camera.CFrame:Lerp(adjustedCameraCFrame, cameraLerpAlpha)
            if cameraLerpAlpha >= 1 then
                transitioningToCamera = false
            end
        else
            camera.CFrame = adjustedCameraCFrame
        end
    elseif transitioningToDefault then
		local targetCameraCFrame = hrp.CFrame * defaultCameraOffset
		
        deactivationLerpAlpha = math.clamp(deactivationLerpAlpha + dt * cameraLerpSpeed, 0, 1)
        camera.CFrame = camera.CFrame:Lerp(targetCameraCFrame, deactivationLerpAlpha)

        if deactivationLerpAlpha >= 1 then
            transitioningToDefault = false
            camera.CameraType = defaultCameraType
            camera.CameraSubject = humanoid
            humanoid.AutoRotate = defaultAutoRotate
            uis.MouseBehavior = Enum.MouseBehavior.Default

            local heartbeatConnection
            heartbeatConnection = runService.Heartbeat:Connect(function()
                camera.CameraType = defaultCameraType
                camera.CameraSubject = humanoid
                heartbeatConnection:Disconnect()
            end)
        end
    end
end)

char.Destroying:Connect(function()
    if renderConnection then
        renderConnection:Disconnect()
    end
    uis.MouseBehavior = Enum.MouseBehavior.Default
    camera.CameraType = defaultCameraType
    camera.CameraSubject = humanoid
    humanoid.AutoRotate = defaultAutoRotate
end)

Nevermind, I found a solution.