I’ve run into an issue with TouchRotate where if I start one rotation with 2 fingers, keep one of the fingers on the screen, and then rotate again, it causes the rotation to sorta jump if that makes sense?

I don’t know how to describe it so I haven’t been able to find any solutions, here’s a video. Gray squares are where my fingers are:

Script:

userInputService.TouchRotate:Connect(function(touchPositions, rotation, velocity, state, gameProcessedEvent)
if #touchPositions < 2 then -- argument from userInputService.TouchRotate
cameraRotationAtBeginningOfTouchRotate = nil
return
end
if #touchPoints < 2 then -- also manually keeping track of the amount of fingers on the screen which is the touchPoints table, as a fallback
cameraRotationAtBeginningOfTouchRotate = nil
return
end
canPanCamera = false -- disable panning
if not cameraRotationAtBeginningOfTouchRotate then -- if it's nil, this is the start of a rotation
cameraRotationAtBeginningOfTouchRotate = cameraRotation -- save the current camera rotation as the rotation to apply the offset
end
cameraRotation = cameraRotationAtBeginningOfTouchRotate * CFrame.Angles(0,rotation,0) -- the offset
end)

It looks like the code sample on the dev hub gets it right from minimal testing.

local cameraRotation = Vector2.new(0, math.rad(-60))
-- ...
local function UpdateCamera()
SetCameraMode() -- doesn't do anything with cameraRotate
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0)
* CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame
+ cameraPosition
+ cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
-- ...
local lastTouchRotation = nil
-- gets connected to UserInputService.TouchRotate
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
local rotationDelta = -difference
* math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
cameraRotation += Vector2.new(rotationDelta, 0)
UpdateCamera()
end
lastTouchRotation = rotation
end

Something must have been wrong with how I was handling it, works now.

Main differences are that I’m using the difference between the last, and I’m not discarding anything at the beginning of the function if conditions aren’t met.

userInputService.TouchRotate:Connect(function(touchPositions, rotation, velocity, state, gameProcessedEvent)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation *= CFrame.Angles(0,-difference,0)
end
lastTouchRotation = rotation
end)