Need help with CFrame:Lerp()

I’m having this problem where the Lerp isn’t executing properly. Instead it sorts of ‘vibrates’(?).

I want it so it goes to the camera, but it does that for some reason.


	local n = (1 / deltaTime) / 60
	weapon.DELTA_TIME = deltaTime
	if viewmodel:FindFirstChild('HumanoidRootPart') then

        -- theres supposed to be like 50 lines of code up here but the main code is here

		if weapon.AIMING then
			print(weapon.SIGHT.CFrame:Lerp(workspace.Camera.CFrame, deltaTime))
			weapon.SIGHT.CFrame = weapon.SIGHT.CFrame:Lerp(workspace.Camera.CFrame, deltaTime)



So I replaced ‘deltaTime’ with 1 and with that it instantly teleports to the camera and also the vibration is probably from the delta changing. Still don’t know why it dosen’t lerp.


Tried using a loop to update the lerp, still dosen’t work.


Trying to use springs.

Any help would be appreciated!

1 Like

Something else is causing the weapon to go back to its original position instead of lerping towards the camera CFrame, make sure that’s the only CFrame change operation going on.

I put that code at the end unless I’m missing something?


I’ve also tried just commenting out all of the code except the AIMING lerp, still does the same thing.
I also tried this:

if weapon.AIMING then
			--weapon.SIGHT.CFrame = weapon.SIGHT.CFrame:Lerp(workspace.Camera.CFrame, deltaTime)
			weapon.SIGHT.CFrame = workspace.Camera.CFrame

Which works fine dosen’t seem to fight back. But I want it to lerp smoothly.

So I’m pretty sure the vibration is because of deltaTime changing that’s probably why it appears to vibrate but I still have no idea on why it dosen’t lerp.

Are you sure that weapon.SIGHT.CFrame isn’t being changed elsewhere at all somewhere in the 50 lines of code?

If you are doing it every render step even though it goes towards the goal position somewhere in the beginning line of the code it gets reset back to the offset from the camera position.

Even if delta time varies then it would still attempt to lerp slowly towards the goal position and not vibrate as delta time is usually between 0-1

you have to replace the 1 wtih something smaller than 1, maybe that will work better


Only one matching. (from the code above)

I was seeing if it was actually working, that’s why I replaced with 1. It just teleports to the camera (because delta is 1) which means it somewhat works.

Post the entire code?

Are you modifying the CFrame of another part that is welded onto the weapon perhaps the basepart of the weapon?

Then the welds might be fighting against each other one part goes towards camera, another part goes towards the viewmodel position.

Nope, all Motor6D’s are not being changed. The only C0 and C1 changes that I’m aware of is from my equip function

Entire RunService code:

	local n = (1 / deltaTime) / 60
	weapon.DELTA_TIME = deltaTime
	if viewmodel:FindFirstChild('HumanoidRootPart') then

		local distance = (playerHead.CFrame.p - mouse.Hit.p).magnitude
		local difference = playerHead.CFrame.Y - mouse.Hit.Y
		local CamDirection = root.CFrame:toObjectSpace(workspace.Camera.CFrame).LookVector

			local rightX, rightY, rightZ = Rshoulder.C0:ToEulerAnglesYXZ()
			local leftX, leftY, leftZ = Lshoulder.C0:ToEulerAnglesYXZ()

			Rshoulder.C0 = (Rshoulder.C0 * CFAng(0, 0, -rightZ)) * CFAng(0, 0, asin((mouse.Hit.p - mouse.Origin.p).unit.y))
			Lshoulder.C0 = (Lshoulder.C0 * CFAng(0, 0, -leftZ)) * CFAng(0, 0, asin((-mouse.Hit.p - -mouse.Origin.p).unit.y))

		local CameraDirection = Character:WaitForChild("HumanoidRootPart").CFrame:toObjectSpace(camera.CFrame).lookVector

		neck.C0 = CFNew(0, YOffset, 0) * CFAng(3 * math.pi/2, 0, math.pi) * CFAng(0, 0, -asin(CameraDirection.x)) * CFAng(-asin(CameraDirection.y), 0, 0)
		viewmodel.CameraBone.CFrame = workspace.Camera.CFrame
		if leaning ~= false then
			humanoid.CameraOffset =, -math.abs(e * 0.1), 0)
			if e < cameraOffsetOrient then
				e += 0.5
				a = e - 2
			elseif e > cameraOffsetOrient then
				e -= 0.5
				a = 0
			local function init(count)
				workspace.Camera.CFrame *= CFrame.Angles(0, 0, math.rad(count))
				viewmodel.HumanoidRootPart.CFrame = workspace.Camera.CFrame
			if count < countMax then
				count += increment
			elseif count > countMax and math.sign(increment) == -1 then
				count += increment
			elseif count == countMax then
			if leaning == nil and count == countMax then
				leaning = false
		local velocity = Character.HumanoidRootPart.Velocity
		local movementSway =, speed, modifier), getBobbing(5, speed, modifier),getBobbing(5, speed, modifier))
		weapon.SPRINGS.SWAY:shove((movementSway / 25) * deltaTime * 60 * velocity.Magnitude)
		local sway = weapon.SPRINGS.SWAY:update(deltaTime)
		viewmodel.HumanoidRootPart.CFrame = viewmodel.HumanoidRootPart.CFrame:ToWorldSpace( / 4, sway.y / 2, 0))
		local mouseDelta = game:GetService("UserInputService"):GetMouseDelta()
		weapon.SPRINGS.GUN_BOBBLE:shove( / 500 ,mouseDelta.X / 200))
		local gunBobble = weapon.SPRINGS.GUN_BOBBLE:update(deltaTime)
		local gunBobbles = math.deg(gunBobble.X)
		gunBobbles = math.clamp(gunBobble.X, 0, 25)	
		gunBobbles = math.rad(gunBobble.X)
		viewmodel.HumanoidRootPart.CFrame *= CFrame.Angles(gunBobbles, gunBobble.Y, gunBobble.Z)
		local recoil = weapon.SPRINGS.RECOIL:update(deltaTime)
		workspace.Camera.CFrame *= CFrame.Angles(recoil.X*n, recoil.Y*n, recoil.Z*n)
		local kick = weapon.SPRINGS.KICK:update(deltaTime)
		viewmodel.CameraBone.CFrame *=*n, kick.Y*n, kick.Z*n)
		local botPos = bottomCrosshairSpring:update(deltaTime)
		crosshairLower.Bottom.Position =, 0, -botPos.Y, 0)
		crosshairLower.Right.Position =, 0.5, 0.5, 0)
		local upPos = upCrosshairSpring:update(deltaTime)
		crosshairUpper.Up.Position =, 0, -botPos.Y, 0.5)
		crosshairUpper.Left.Position =, 0.5, 0.5, 0)
		if weapon.AIMING then
               weapon.SIGHT.CFrame = weapon.SIGHT.CFrame:Lerp(workspace.Camera.CFrame, deltaTime)

Ok here are some places of concern which is every time a CFrame is being Set.

Is your gun connected to the Viewmodel via rigid weld? Motor6D? Even a bone instance, but idk much about them.

This is what the CFrame lerp towards another constant CFrame should do with delta time.

Part lerping towards another part via delta time
local RunService = game:GetService("RunService")


local part = workspace.Part
local sphere = workspace.Sphere

	part.CFrame = part.CFrame:Lerp(sphere.CFrame, deltaTime)

And here is the vibration effect problem, which you are experiencing right now which happens if the part.CFrame is set to another CFRame before the lerp undoing the effects of the lerp.

Code with glitchy lerp
local RunService = game:GetService("RunService")


local part = workspace.Part
local sphere = workspace.Sphere

	part.CFrame =,5,0)
	part.CFrame = part.CFrame:Lerp(sphere.CFrame, deltaTime)

Do you see the similarities? Something is resetting the viewmodel back to where it was.


Hmm, now that I think about it you are using a viewmodel with a humanoid right? Is it entirely local?

If the viewmodel is not made locally then another possible issue is that the server is resetting the viewmodel back to it’s original position, if so then you will need to set network ownership to the player.

Otherwise, I’m stumped.

How could I prevent this? The viewmodel needs to be updated to the camera every frame. Removing the line would just break the viewmodel parenting. Is there another way?

No, It dosen’t have a humanoid.

Yes the viewmodel is being updated in a local script.

Yep, so I’m assuming that your viewmodel is indeed connected to the gun so that you can perform animations with them. (via Motor6D)

If so you can edit the .C0 of the Motor6D gun which is connected to the humanoidrootpart/Viewmodel instead of directly setting the CFrames of the viewmodel.

To work with world terms with Motor6D’s remember to inverse the Part0 if you are working with the C0 to work in object terms of the Motor6D. motor6D.Part0.CFrame:Inverse() * WorldCFrame you want = camera.CFrame.

What does WorldCFrame supposed to be exactly?

I’m assuming you put the camera’s CFrame to this: motor6D.Part0.CFrame:Inverse() * WorldCFrame, correct?

Sorry to clarify here is the equation for a Motor6D C0:

Motor6d.C0 = Motor6D.Part0.CFrame:Inverse() * WorldCFrame

This has a similar effect to:

Part.CFrame =WorldCFrame

But the inversing is there for the motor6D since the C0 is relative to Part0 which makes it more confusing so we undo it by inversing the part0 CFrame.

WorldCFrame is any CFrame relative to the world like camera.CFrame or part.CFrame.

Hm, wouldn’t this just teleport the gun instead of transitioning it?

Not if you also add lerping to the C0 CFrame towards the goal CFrame.

Alright I tried using your concept which unfortunately did not work. It almost work but since the sight is not the main part it dosen’t bring the gun towards the camera, and also the arms.

Currently I’m trying to use springs.

Hmm, if you want another method that would easily fit with your system that is already implemented.

Just tween the alpha value from 0-1 during aiming. You can do this by creating a number value instance and using the .Changed event to input the new number value into the keep alpha.

Oh my god.

Why haven’t I thought of this earlier. I spent 3 hours looking for solutions :man_facepalming:. This works perfectly! Thank you so much!