First-Third Person Camera System Not Working

I am creating a camera system that toggles between first and third person smoothly. The third person perspective should be over the shoulder at a specific offset, while first person works normally. Current the code below works, however, there is a small bug seen in the video attached:

local CameraOffset = Vector3.new(4,2,8) -- Camera Offset
local running = true
local cameraAngleX = 0
local cameraAngleY = 0
local startCFrame 
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
player.CameraMinZoomDistance = 8
player.CameraMaxZoomDistance = 8

function POV.FocusControl(actionName, inputState, inputObject)
	if inputState == nil or inputState == Enum.UserInputState.Begin then
		camera.CameraType = Enum.CameraType.Scriptable
		player.CameraMode = Enum.CameraMode.Classic
	end
end

UserInputService.WindowFocused:Connect(function()
	if running then
		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	end
end)

POV.FocusControl()

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()
	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))
	if running then
		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)
	end
end)

UserInputService.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.Z  and running then -- FirstPerson
		running = false
		repeat
			camera.CameraType = Enum.CameraType.Custom
		until camera.CameraType == Enum.CameraType.Custom
		player.CameraMode = Enum.CameraMode.LockFirstPerson
	elseif input.KeyCode == Enum.KeyCode.Z then -- ThirdPerson 
		running = true
		POV.FocusControl()
	end
end)

After returning from first-person back to third-person. The more input.Delta.X that occured while in first person the more the camera’s CFrame will snap a random X direction while the camera’s Y CFrame stays relatively the same when transitioning back to third-person.

After hours of debugging I have realized that Roblox’s mouse sensitivity and how long it would take to do a 360 turn when in first-person vs third-person is different. Although I never change mouse.DeltaSensitivity, inputObject.Delta.X scales different when in first-person vs third-person. Is there a way around this or to account for the change in sensivity, looking at other bug threads I saw Roblox’s mouse sensitivity system has been an issue for a long time.

2 Likes