Stop orientation on Z axis whilst changing Y and X

Hello devs,

Im trying to create a freecam system, however its moving abnormally and i deem this to be down to the Z axis orientation being changed is there a way to keep it fixed to 0, here is my script.

function updateCameraRotation()
	if isMouseLocked then
		local deltaMouse = Vector2.new(mouse.X, mouse.Y) - lastMousePosition

		-- Calculate horizontal rotation (around y-axis)
		local yawRotation = CFrame.Angles(0, math.rad(-deltaMouse.x * mouseSensitivity), 0)

		-- Calculate vertical rotation (around x-axis)
		local pitchRotation = CFrame.Angles(math.rad(-deltaMouse.y * mouseSensitivity), 0, 0)

		-- Combine yaw and pitch rotations
		local combinedRotation = yawRotation * pitchRotation

		-- Apply combined rotation to the camera's orientation
		camera.CFrame = camera.CFrame * combinedRotation
	end
end

Try adding this after the “Apply combined rotation”

-- Reset rotation around Z-axis to keep it fixed
camera.CFrame = camera.CFrame * CFrame.Angles(0, 0, -camera.CFrame:ToEulerAnglesXYZ().z)

I can’t test this, because you didn;t supply the full script, but hopefully it works.

Unfortunately it bugs out the entire camera and starts causing it to go wavy is the best way to describe it with the error of attempt to index number with 'z'

Can you supply the rest of the script that controls the freecam?

local UserInputService = game:GetService("UserInputService")

local camera = game.Workspace.CurrentCamera
local player = game.Players.LocalPlayer
local mouse = game:GetService("Players").LocalPlayer:GetMouse()

-- Configuration
local mouseSensitivity = 0.3
local movementSpeed = 1

local Isinmode = false
local isMouseLocked = false
local lastMousePosition = nil

-- Variables to store saved camera settings
local savedCameraCFrame = nil
local savedCameraMode = nil
local savedCameraType = nil
local savedCameraMinZoom = nil

-- Function to lock/unlock mouse
local function toggleMouseLock()

	if isMouseLocked == false then
		isMouseLocked = true
		-- Save current camera settings

		--UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
		mouse.Icon = "rbxasset://textures/Cursors/CrossMouseIcon.png"
		--		player.CameraMode = Enum.CameraMode.LockFirstPerson

	else
		isMouseLocked = false


		UserInputService.MouseBehavior = Enum.MouseBehavior.Default

		mouse.Icon = "rbxasset://textures/Cursors/KeyboardMouse/ArrowFarCursor.png"
	end
	print("isMouseLocked:", isMouseLocked)
end

-- Toggle mouse lock on right-click
UserInputService.InputBegan:Connect(function(input, isProcessed)
	if input.UserInputType == Enum.UserInputType.MouseButton2 then
		if Isinmode == true then
			toggleMouseLock()
		end


	end
end)

-- Toggle freecam mode on UI button click
script.Parent.MouseButton1Click:Connect(function()
	print(Isinmode)
	if Isinmode then
		Isinmode = false
		-- Toggle freecam mode
		camera.CFrame = savedCameraCFrame or camera.CFrame
		player.CameraMode = savedCameraMode or player.CameraMode
		game.Workspace.CurrentCamera.CameraType = savedCameraType or game.Workspace.CurrentCamera.CameraType
		player.CameraMinZoomDistance = savedCameraMinZoom or player.CameraMinZoomDistance
		isMouseLocked = true
		toggleMouseLock()

	else
		Isinmode = true
		savedCameraCFrame = camera.CFrame
		savedCameraMode = player.CameraMode
		savedCameraType = game.Workspace.CurrentCamera.CameraType
		savedCameraMinZoom = player.CameraMinZoomDistance
		player.CameraMaxZoomDistance = 0
		player.CameraMinZoomDistance = 0

		workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
	end
end)

-- Update camera rotation
-- Function to update camera rotation with vertical clamping and locked z position
function updateCameraRotation()
	if isMouseLocked then
		local deltaMouse = Vector2.new(mouse.X, mouse.Y) - lastMousePosition

		-- Calculate horizontal rotation (around y-axis)
		local yawRotation = CFrame.Angles(0, math.rad(-deltaMouse.x * mouseSensitivity), 0)

		-- Calculate vertical rotation (around x-axis)
		local pitchRotation = CFrame.Angles(math.rad(-deltaMouse.y * mouseSensitivity), 0, 0)

		-- Combine yaw and pitch rotations
		local combinedRotation = yawRotation * pitchRotation

		-- Apply combined rotation to the camera's orientation
		camera.CFrame = camera.CFrame * combinedRotation
	end
end


-- Update camera movement
game:GetService("RunService").RenderStepped:Connect(function()




	local moveVector = Vector3.new(0, 0, 0)
	if Isinmode == true then
		if isMouseLocked == true then
			if lastMousePosition then
				updateCameraRotation()
				print("Updating CameraRotation")
			end
			lastMousePosition = Vector2.new(mouse.X, mouse.Y)
		end
		if player then


			local cam = game.Workspace.CurrentCamera
			local cframe = cam.CFrame
			local forward = cframe.LookVector
			local right = cframe.RightVector
			local up = cframe.UpVector

			if UserInputService:IsKeyDown(Enum.KeyCode.W) then
				moveVector = moveVector + forward
				print("Forward")
			end
			if UserInputService:IsKeyDown(Enum.KeyCode.S) then
				moveVector = moveVector - forward
			end
			if UserInputService:IsKeyDown(Enum.KeyCode.A) then
				moveVector = moveVector - right
			end
			if UserInputService:IsKeyDown(Enum.KeyCode.D) then
				moveVector = moveVector + right
			end
			if UserInputService:IsKeyDown(Enum.KeyCode.E) then
				moveVector = moveVector + up
			end
			if UserInputService:IsKeyDown(Enum.KeyCode.Q) then
				moveVector = moveVector - up
			end

		end
	end

	camera.CFrame = camera.CFrame * CFrame.new(moveVector * movementSpeed)
end)
```