How to stop camera tilt accumulating each frame

I’ve been dealing with this issue already for like 2 days trying to figure out how to stop the camera tilt accumulating each frame, I am not that good with camera manipulation so if anyone that knows a bit more about camera manipulation, any help is really appreciated.

Here is the camera tilt code I use

if self.torso and self.rootpart then
	local movementVector = currentCamera.CFrame:VectorToObjectSpace(self.rootpart.AssemblyLinearVelocity / 100)
	local sideMovement = math.clamp(movementVector.X/7, -0.25, 0.25)
	sideCameraTilt = lerp(sideCameraTilt, sideMovement, 0.1 * frameDelta)
	local Neck = self.torso:FindFirstChild("Neck")
	local RootJoint = self.rootpart:FindFirstChild("RootJoint")
	local NTX,NTY,NTZ = Neck.Transform:ToEulerAnglesXYZ()
	local RTX,RTY,RTZ = RootJoint.Transform:ToEulerAnglesXYZ()
	cameraTiltAngle = CFrame.Angles(math.rad(NTY/3), 0, math.rad((NTZ-RTZ)) - sideCameraTilt)
end

currentCamera.CFrame = newCameraCFrame * cameraTiltAngle

Here is a video of the problem I am having

I did tried using clamp but since the camera tilt just keeps adding up each frame, it really doesn’t work.

I do not know what the rest of your code looks like, but maybe this would work? I am not too knowledgable on CFrame, try changing the value in the if statement.

if self.torso and self.rootpart then
	local movementVector = currentCamera.CFrame:VectorToObjectSpace(self.rootpart.AssemblyLinearVelocity / 100)
	local sideMovement = math.clamp(movementVector.X/7, -0.25, 0.25)
	sideCameraTilt = lerp(sideCameraTilt, sideMovement, 0.1 * frameDelta)
	local Neck = self.torso:FindFirstChild("Neck")
	local RootJoint = self.rootpart:FindFirstChild("RootJoint")
	local NTX,NTY,NTZ = Neck.Transform:ToEulerAnglesXYZ()
	local RTX,RTY,RTZ = RootJoint.Transform:ToEulerAnglesXYZ()
	
	cameraTiltAngle = CFrame.Angles(math.rad(NTY/3), 0, math.rad((NTZ-RTZ)) - sideCameraTilt)
	
	if cameraTiltAngle.X > 30 then -- maybe change this number??
		cameraTiltAngle = CFrame.Angles(math.rad(30), 0, math.rad((NTZ-RTZ)) - sideCameraTilt)
	end
end

currentCamera.CFrame = newCameraCFrame * cameraTiltAngle

can you provide some more of the script so we can see where the code is running

Oh sure, here. It’s part of the CameraModule that Roblox provides by default.

local newCameraCFrame, newCameraFocus = self.activeCameraController:Update(dt)
if self.activeOcclusionModule then
	newCameraCFrame, newCameraFocus = self.activeOcclusionModule:Update(dt, newCameraCFrame, newCameraFocus)
end
		
-- Here is where the new CFrame and Focus are set for this render frame
local currentCamera = game.Workspace.CurrentCamera :: Camera
local cameraTiltAngle = CFrame.Angles(0,0,0)
		
if self.torso and self.rootpart then
	local movementVector = currentCamera.CFrame:VectorToObjectSpace(self.rootpart.AssemblyLinearVelocity / 100)
	local sideMovement = math.clamp(movementVector.X/7, -0.25, 0.25)
	sideCameraTilt = lerp(sideCameraTilt, sideMovement, 0.1 * frameDelta)
	local Neck = self.torso:FindFirstChild("Neck")
	local RootJoint = self.rootpart:FindFirstChild("RootJoint")
	local NTX,NTY,NTZ = Neck.Transform:ToEulerAnglesXYZ()
	local RTX,RTY,RTZ = RootJoint.Transform:ToEulerAnglesXYZ()
	cameraTiltAngle = CFrame.Angles(math.rad(NTY/3), 0, math.rad((NTZ-RTZ)) - sideCameraTilt)
end
		
currentCamera.CFrame = newCameraCFrame * cameraTiltAngle

Basically newCameraCFrame is the result after doing the whole math to get the positions and rotations of the camera, then I want to apply the tilt, the problem is that on each next frame, the tilt is also included in the newCameraCFrame, so I assume that’s why it accumulates, I know why it happens but I don’t know how to fix it at all.

This doesn’t really do much, I tried and it still happens…

instead of setting cameratiltangle using the absolute angles of the rootjoint and neck transforms, you can find the change in these angles every frame. you can do that like this:

At the top of the script:

local _, lastNTY, lastNTZ = Neck.Transform:ToEulerAnglesXYZ()
local _, _, lastRTZ = RootJoint.Transform:ToEulerAnglesXYZ()

in the update function:

local _, NTY, NTZ = Neck.Transform:ToEulerAnglesXYZ()
local _, _, RTZ = RootJoint.Transform:ToEulerAnglesXYZ()
local dNTY = NTY - lastNTY
local dNTZ = NTZ - lastNTZ
local dRTZ = RTZ - lastRTZ
cameraTiltAngle = CFrame.Angles(dNTY, 0, dNTZ-dRTZ - sideCameraTilt)
lastNTY = NTY
lastNTZ  = NTZ
lastRTZ = RTZ

you might need to do thesame for sidecameratilt

It kind of works, it does fix the accumulating but now the camera tilt is messed up-

Did you do thesame for sidecameratilt? I think the Z axis could also be messed up because i was supposed to find the change in (NTZ-RTZ) every frame, instead of doing dNTZ-dRTZ,

I removed the side tilt value and its still messed up, so I doubt that’s the problem