Hey all,
I know this is a topic that has a lot of threads, and I’ve searched for quite a few hours and all of the solutions I’ve found were at least one of the following
- not conclusive
- didn’t explain how to use the solution
- didn’t work at all
For those who are unaware, when you try and lerp the camera to a moving object, the moving object will appear to jitter or stutter because of rendering issues. Though, I’m still uncertain as to what it is exactly that causes these rendering issues.
From what I’ve gathered:
- using a
.Stepped
loop as opposed to aRenderStepped
loop should work, but for whatever reason doesn’t. - Using the interpolation formula,
1 - CONST / (DT + CONST)
, whereCONST
is the reciprocal of your desired framerate andDT
is the delta time doesn’t seem to work either. - this solution: Issues with scripted camera stuttering - #6 by NovusTheory, but with lerp instead of springs
I feel like I should use the spring module, but I searched for a spring module that should work for this, and I couldn’t find one, or there was no API documentation for the ones I did find.
Here’s my code. Unfortunately, I can’t get a video up, but if you paste this code into a LocalScript
in StarterPlayerScripts
you can see what happens. It’s not stuttering, but it’s refusing to lerp for the first one, but for the second it lerps but also stutters.
Code that doesn't lerp the camera but doesn't stutter
local rs = game:GetService("RunService")
local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hrp = char:WaitForChild("HumanoidRootPart")
local cam = workspace.CurrentCamera
local CONST = (1/60)
local mouse = player:GetMouse()
local maxTilt = 5
lastPhysicsDeltaTime = 0
lastFramesDeltaTime = 0
lastCFrame = nil
repeat
task.wait()
cam.CameraType = Enum.CameraType.Scriptable
until
cam.CameraType == Enum.CameraType.Scriptable
rs.Stepped:Connect(function(t, dt)
local mousecf = CFrame.Angles(
math.rad((((mouse.Y - mouse.ViewSizeY / 2) / mouse.ViewSizeY)) * -maxTilt),
math.rad((((mouse.X - mouse.ViewSizeX / 2) / mouse.ViewSizeX)) * -maxTilt),
0
)
local campos = Vector3.new(0, 20, 6)
local camrot = CFrame.fromEulerAnglesXYZ(math.rad(-65), 0, 0)
local targetCFrame = (CFrame.new(hrp.Position + campos) * camrot * mousecf)
if ((not lastCFrame) or not (lastCFrame == targetCFrame)) then
local trueDT = lastFramesDeltaTime + lastPhysicsDeltaTime
print(1 - CONST / (trueDT + CONST))
cam.CFrame = cam.CFrame:Lerp(targetCFrame, 1 - CONST / (trueDT + CONST))
lastCFrame = targetCFrame
lastFramesDeltaTime = 0
else
lastFramesDeltaTime = dt
end
end)
while true do
local discard
discard, lastPhysicsDeltaTime = rs.Stepped:Wait()
end
Code that lerps the camera but stutters
local rs = game:GetService("RunService")
local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hrp = char:WaitForChild("HumanoidRootPart")
local cam = workspace.CurrentCamera
local mouse = player:GetMouse()
local maxTilt = 5
repeat
task.wait()
cam.CameraType = Enum.CameraType.Scriptable
until
cam.CameraType == Enum.CameraType.Scriptable
rs:BindToRenderStep("CameraStep", 203, function()
local mousecf = CFrame.Angles(
math.rad((((mouse.Y - mouse.ViewSizeY / 2) / mouse.ViewSizeY)) * -maxTilt),
math.rad((((mouse.X - mouse.ViewSizeX / 2) / mouse.ViewSizeX)) * -maxTilt),
0
)
local targetCF = CFrame.new(hrp.Position + Vector3.new(0, 20, 6)) * CFrame.fromEulerAnglesXYZ(math.rad(-65), math.rad(0), math.rad(0)) * mousecf
cam.CFrame = cam.CFrame:Lerp(targetCF, 0.05)
end)
At the end of the day, all I’m looking for is a definitive answer to this problem because its pretty frequent and its surprising how little explanation or resolution there is for this.