Camera Bob Is Too Snappy, How Can I Smooth It?

I’m looking at improving some code I wrote a couple years ago for a project and something that has always irked me about this code is the fact that, when starting and stopping movement, the camera snaps from its resting position to whatever the output of the sine or cosine function is at that given time. Point being, I’d like the whole process from initiating movement and stopping movement to be smoother camera-wise. Below is my code, any tips?

function updateBobbleEffect()
	local currentTime = tick()
	if humanoid.MoveDirection.Magnitude > 0 then
		if humanoid.WalkSpeed <= 7 then
			local bobbleX = math.sin(currentTime * 4) * .20
			local bobbleY = math.abs(math.sin(currentTime * 5)) * .20
			
			local rotBobbleZ = math.sin(currentTime * 5) * .01

			local bobble = Vector3.new(bobbleX, bobbleY, 0)

			humanoid.CameraOffset = humanoid.CameraOffset:lerp(bobble, .25)
			workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame * CFrame.Angles(0,0,rotBobbleZ)
		elseif humanoid.WalkSpeed > 7 then
			local bobbleX = math.sin(currentTime * 7) * .20
			local bobbleY = math.abs(math.sin(currentTime * 7)) * .20
			
			local rotBobbleX = math.sin(currentTime * 10) * .001
			local rotBobbleZ = math.sin(currentTime * 5) * .01
			
			local bobble = Vector3.new(bobbleX, bobbleY, 0)
			
			humanoid.CameraOffset = humanoid.CameraOffset:lerp(bobble, .25)
			workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame *  CFrame.Angles(rotBobbleX,0,rotBobbleZ)
		end
	elseif humanoid.MoveDirection.Magnitude == 0 then

		local bobbleY = math.abs(math.sin(currentTime * 1)) * .05    
		
		local rotBobbleZ = math.sin(currentTime * 0.01) * .001

		local bobble = Vector3.new(0, bobbleY, 0)
		
		humanoid.CameraOffset = humanoid.CameraOffset:lerp(bobble, .15)
		workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame *  CFrame.Angles(0,0,rotBobbleZ)
	else 
		humanoid.CameraOffset = humanoid.CameraOffset * .75
	end
end
2 Likes

One way you could do this:

  • Instead of using the current time, use a variable, say, bobblePos. Then, instead of using currentTime * speed factor for your sin functions, use bobblePos and increase bobblePos by something like speedFactor/40 every frame. This makes it so the sine function position is continuous
  • Now you just need to make the sine amplitude continuous. To do this, create variables called “sineApplitude” and “sineApplitudeTarget”. Change sineApplitudeTarget to the applitude for the given speed (e.g. 0.2 for speed > 7). Then, interpolate sineApplitude to sineApplitudeTarget over time using:
-- Smoothly moves sineApplitude to sineApplitudeTarget
interpolateFactor = 0.05 -- make this smaller if it updates too fast
sineApplitude = (1-interpolateFactor) * sineApplitude + interpolateFactor * sineApplitudeTarget
  • Now all your sine waves should be continuous, even as the desired speed and amplitude change! You can do this same thing for each of your sine waves (e.g. also the ones for rotation).
1 Like

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