Lerp lagging behind intended position

  1. What do you want to achieve? Keep it simple and clear!

I’m working on camera controls for this plane. There are two camera modes, one is the chase camera, and the other camera mode allows the player to look around freely—this camera mode is activated when the player is holding down C on the keyboard. When the player stops pressing C, instead of having the camera snap back to the original position in the chase camera mode, the transition is smoothed using a lerp function.
I got it to work but the problem is that at the end of the lerp, the camera position is lagging behind of where it should be, and the problem becomes more apparent when the plane’s speed increases.
How do I fix this?

This snipet runs in a RunService.Heartbeat connection
newCF what the camera CFrame would be updated to every frame in the chase/follow camera mode, and it’s also the target CFrame in the lerp

the calculations for newCF is made right before the snipet below, but it’s pretty long so I omitted it

	if cameraMode == "Follow" then --chase camera
		if lerpComplete then
			cam.CFrame = newCF --updates camera CFrame in chase mode
			if lerpAlpha ~= 0 then
				lerpAlpha = 0
				print("camera lerp complete")
			end
		else --free look camera mode lerping to chase camera
			cam.CFrame = cam.CFrame:Lerp(newCF, lerpAlpha)
			if lerpAlpha >= 1 then lerpComplete = true end
			lerpAlpha += lerpIncrement
		end
	end

in the video I pressed C repeatedly, and each time I let go of the C-key which triggers the lerp, you can see that the camera ends up lagging far behind the plane than it should be for a brief moment.

btw the lerp works just fine when the speed of the plane is near zero:

1 Like

I think for a camera controller like this you would be better off using RunService.RenderStepped rather than RunService.Heartbeat.

1 Like

I tried using :BindToRenderStep for the camera update function, it did not solve the issue and also added jittering.

1 Like

If you interpolate the entire CFrame, you also end up lerping the position of the CFrame. Instead, separate the position and rotation of the CFrame, lerp the rotation, and combine them.

Example (NOT TESTED):

local CF = CFrame.new(20, 0, 20) * CFrame.Angles(0, math.rad(180), 0)

local Positional, Rotational = CFrame.new(CF.Position), CF - CF.Position

Rotational:Lerp(CFrame.Angles(0, math.rad(90),0), 0.5)

CF = Positional * Rotational

I saw other posts that separated position and rotation for the solution, but this is not it. I need to lerp the position of the CFrame, not just the rotation, otherwise it would still look like the camera just teleported to the back of the plane.
I also tried predicting the position of the plane by half a frame, it did not seem that the discrepancy between the lerped position and intended position is directly proportional to the plane’s velocity either.

How did you CFrame then? Can you provide the code where the CFrame calculations of the camera take place?

Is your plane movement controlled by the server? Because I believe that for vehicles, you need to let them be controlled by the client because there’s always a delay for replication from the server to client.

I found a solution to it, I lerped just the rotational CFrame like Y_VRNDLL described, but in addition to that I calculated a new position based on the lerped orientation and create a new CFrame with the new position and lerped rotation combined, setting the camera CF to that CFrame.

Also I completely reworked how the camera CFrame is calculated, not just the lerping so everything I said before is no longer applicable.

(new camera based on cursor world position)

--cursor is an instance of a class that i made
local cursorWorldPos = cursor:getWorldPosition()
local targetRotation = CFrame.new(plane.Cm.Position, cursorWorldPos)
targetRotation = targetRotation.Rotation
targetRotation = cam.CFrame.Rotation:Lerp(targetRotation, .05)
		
local targetPosition = -targetRotation.LookVector * plane.CamDistance
targetPosition += plane.Camera.CenterPart.Position			
		
cam.CFrame = CFrame.new(targetPosition) * targetRotation
1 Like

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