Camerasway is not consistent on all framerates despite there being delta time

I’ve been trying to fix this issue for so long, anyone know how I can make my camera sway consistent on all framerates

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera
local Turn = 0

local MaxSwayAmount = 6 
local SwaySpeed = 3

local function UpdateCamera(deltaTime)
    local MouseDelta = UserInputService:GetMouseDelta().X
    local swayAmount = math.clamp(MouseDelta, -MaxSwayAmount, MaxSwayAmount)
    Turn = Turn + (swayAmount - Turn) * SwaySpeed * deltaTime
    Camera.CFrame = Camera.CFrame * CFrame.Angles(0, 0, math.rad(Turn))
end

RunService.RenderStepped:Connect(function(deltaTime)
    UpdateCamera(deltaTime)
end)

deltatime is also literally present in the code, idk what im doing wrong

There was a fix explained in the framerate update post, however I don’t know if it works since my computer has the exact performance as a potato.

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera
local Turn = 0

local MaxSwayAmount = 6 
local SwaySpeed = 3

local TargetFPS = 60

local function UpdateCamera(deltaTime)
	local MouseDelta = UserInputService:GetMouseDelta().X
	local swayAmount = math.clamp(MouseDelta, -MaxSwayAmount, MaxSwayAmount)
	Turn = Turn + (swayAmount - Turn) * SwaySpeed * deltaTime
	Camera.CFrame = Camera.CFrame * CFrame.Angles(0, 0, math.rad(Turn))
end

RunService.RenderStepped:Connect(function(deltaTime)
	UpdateCamera(math.rad(TargetFPS) * deltaTime)
end)
1 Like

Thanks for helping me but I’ve tried the code and it doesn’t seem to work sadly.

I can explain but TL;DR you need a different calculation method.

The issue is actually both your positive and negative term. For the positive term it is proportional to delta time to more fps means less sway so that means you actually have to turn the mouse more to compensate.

Then there is the issue of the negative term which is recursive sequence.

    Turn = Turn + (swayAmount - Turn) * SwaySpeed * deltaTime
    Turn += (swayAmount - Turn) * SwaySpeed * deltaTime
--Expand just the positive and negative turn
    Turn += (swayAmount) * SwaySpeed * deltaTime
Turn  = Turn  - Turn *SwaySpeed*deltaTime --the negative term
a(n) = a(n-1) - a(n-1)*SwaySpeed*deltaTime --Desmos terms, the new value is determined by the old value of Turn

This can be graphed in desmos in 2 scenarios, 1 assuming fps is 60 and another assuming its 30 fps and the sway term Turn in degrees starts at 20 degrees. Sway speed is a constant value of 3.

As you can see it’s not the same meaning you need a better/different method.

I have remade it but instead of a recursive asymptotical formula replacing it with a linear term with a constant decrease of 10 degrees per second.

This is tbh not as good as the previous as the shape of the curve is not the same, so you should rework it perhaps by adding acceleration.

From this I recommend using another calculation method, perhaps a spring module or something instead which already takes into account acceleration and you can prevent overshoot by increasing dampening or removing velocity.

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera
local Turn = 0

local MaxSwayAmount = 6 
local SwaySpeed = 3

local decreaseSpeed = 10

local function UpdateCamera(deltaTime)
	local MouseDelta = UserInputService:GetMouseDelta().X
	local increaseSway = MouseDelta*0.1
	Turn += increaseSway
	local swayDecreaseIncrement = decreaseSpeed*deltaTime*math.sign(Turn)
	if math.abs(swayDecreaseIncrement) >= math.abs(Turn) then--prevent overshoot
		Turn -= Turn
	else
		Turn -= swayDecreaseIncrement
	end
	Camera.CFrame = Camera.CFrame * CFrame.Angles(0, 0, math.rad(Turn))
end

RunService.RenderStepped:Connect(function(deltaTime)
	UpdateCamera(deltaTime)
end)

Update I think the correct term for this is frame rate independent lerp and something to do with exponential decay, this should be it.