Lerp has stutter?

I’m trying to make a smooth camera that follows the player around, currently it works but one of the main problems is that it jitters or stutters behind the player or sometimes even goes infront of the player at times causing it not to be smooth at all.

CurrentCamera.CFrame = CFrame.new(
	Lerp(LastX, workspace.campart.Position.X, 0.2),
	Lerp(LastY, workspace.campart.Position.Y, 0.1),
	Lerp(LastZ, workspace.campart.Position.Z, 0.2)
) -- Everything below this point is for Camera rotation and distance.
	* Vector3ToRadians(cameraRotation, 0, 1, 0)
	* CFrame.new(0, 1.5, 0)
	* Vector3ToRadians(cameraRotation, 1, 0, 0)
	* CFrame.new(0, 0, cameraDistance)

DebugInfo:UpdateInfo("Camera CFrame", CurrentCamera.CFrame) -- Updates my Debug HUD.
-- Stores the Last Values to be used in the lerp.
LastY = workspace.campart.Position.Y
LastX = workspace.campart.Position.X
LastZ = workspace.campart.Position.Z

This is the code for the camera.

local function Lerp(a, b, alpha)
	return a + ((b - a) * alpha)
end

local function Vector3ToRadians(v1)
	return CFrame.Angles(math.rad(v1.X), math.rad(v1.Y), math.rad(v1.Z))
end

These are my 2 functions used in the code for the camera.

This is all ran in a RenderStepped under the function UpdateCamera, Server Ownership does not change anything, it being on a BasePart or the Roblox Character itself doesn’t change anything as well. The custom Lerp function also doesnt change anything as just using a Vector3 or CFrame Lerp does the exact same thing and im completely stumped.

Examples of the stutter:

Demo File, script is in StarterPlayerScripts, Ignore “campart”
DemoFile.rbxl (54.3 KB)

Where do you update the campart? Plus is this supposed to slightly lag behind the player character?

1 Like

You can substitute the CamPart for the actual players PrimaryPart, I was using the CamPart as a test part falling from the sky to make sure that it wasn’t the Roblox Character causing the issue.

And yes, what its supposed to do is make it smoothly follow behind the player, the way I am doing it is so I can make it so I can change how much I want on X,Y, and Z.

1 Like

Try using RunService.RenderStepped to update your camera CFrame.
If it doesn’t works i recommend using CFrame:Lerp() instead and see the results

1 Like

Please check that you’re updating your camera position before the screen is rendered. The issue usually happens when priorities are ambiguous (ie game sometimes draws the screen first then moves camera or does the opposite, leading to stuttering).

I recommend BindToRenderStep since you can specify the priority. This lets you ALWAYS run the camera movement function BEFORE the screen is drawn for that frame.

-- specify the name of the render action, the priority/order in which it executes during rendering, and the function to execute
RunService:BindToRenderStep("CustomCamLerp", Enum.RenderPriority.Camera.Value - 1, function(dt)
	CurrentCamera.CFrame = CFrame.new()
end)
2 Likes

I stated here that I am running it all under a RenderStepped, and I already mentioned that CFrame or Vector3 Lerps also yield the same results.

From looking at your math code I don’t see rounding errors being a problem.

There is some weird argument passing going on in your code though, you’re passing 4 arguments into a 1 arg function.

I notice you’re also referencing a “campart”. The campart should be moved on the client side and also controlled by .RenderStepped or something similar. I recommend you remove campart completely unless it serves a better purpose than storing position since an internal variable can do the same trick.

How does campart work? If you’re using some kind of roblox force/physics/constraint object maybe that’s the culprit.

Up here I said you can substitute the CamPart for the players PrimaryPart as I used the CamPart for testing with a unanchored BasePart falling from the sky which yielded the same result as using the players PrimaryPart, with the Vector3ToRadians I copied the wrong function into the post, sorry for that.

Here’s the correct function

local function Vector3ToRadians(v1, xMultiplier, yMultiplier, zMultiplier)
	xMultiplier = xMultiplier ~= nil and xMultiplier or 1
	yMultiplier = yMultiplier ~= nil and yMultiplier or 1
	zMultiplier = zMultiplier ~= nil and zMultiplier or 1

	return CFrame.Angles(math.rad(v1.X * xMultiplier), math.rad(v1.Y * yMultiplier), math.rad(v1.Z * zMultiplier))
end

I’m as much stumped as you. I feel like everything given so far looks fine. I’d need to take a look at a demo file for any more information, either posted here or privately sent.

If that’s something you’re not comfortable with I’d recommend you to start removing features to see if the problem goes away. There’s a lot of moving pieces in your system.

  • try removing the rotational components
  • try removing the translation component
  • try returning back to using PrimaryPart to control the camera position
  • try focusing on just 1 component, ie z or x CFrame component
  • try not moving at all and just “faking” player movement by adding/subtracting numbers to see how the system reacts (ie teleport the player back and forth to see how the camera reacts)
  • try a different stepper pipeline like :BindToRenderStep instead of .RenderStepped

Honestly, from what I’ve gathered from attempting this myself, the real holdback is the fact that character’s position is updated post Stepped but the camera itself is updated RenderStepped. Which makes the character’s to-be position, out of sync with the delta time of the renderstepped. Which is why you see that rubber-banding type effect…

You will get inconsistent movement from your lerp with an unstable fps. Try sending DeltaTime (or somevalue *dt) to your lerp functions. I don’t know if that is what is causing the jerkiness though

I uploaded a demo file to the original post, the script is in StarterPlayerScripts, most of it’s commented.

Ignore “campart” it is not being used.

The change in position is not consistent in the function, even if the player is moving at the same speed in-game. This becomes much more noticeable at high speeds. This is caused by changes in the time delta between each frame, which fluctuates.

I’ve tested this with other methods of lerping camera movement, but the problem is still there. This is just something that happens on the Roblox engine that can’t be controlled.

Normally you don’t notice this at slow speeds, but at faster speeds you’ll see it. I would recommend to not lerp at higher speeds.

It’s still a bit noticeable at low speeds as well, is there any way I can make this work at any speed or am I gonna have to just scrap the idea of a smooth camera? Lerping and deltaTime confuses me a bunch so I have no idea how I would do this.

It depends on the game you’re making.
I’ve attached a demo place below.

  1. You could probably keep the same camera system even if it stutters. The system can work well at low speeds. I’ve written extra code to “pad” the camera more so that the stuttering effect is less seen at slower speeds.
    (See attached Woah script)

  2. You could take advantage of roblox’s physics engine which does a lot of close loop feedback stuff (See attached Woah2 script)

  3. You could lock the camera to the player and be done with it. (See attached Woah3 script)

  4. ??? Maybe someone else on the forum has a better implementation.

Other than that, I hope this helps. Good luck!

ReplicationFile_treebee63.rbxl (57.6 KB)

2 Likes

This helps a lot, especially the first demo! Hopefully in the future I can find a better way to do this but for now this will do, thank you and everyone else for helping!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.