How to make a smooth camera bobbing

hi guys what should i adjust to make bobbing more smooth

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera
local humanoid = LocalPlayer.Character.Humanoid
local Turn = 0

local Lerp = function(a, b, t)
	return a + (b - a) * t
end;

RunService:BindToRenderStep("CameraSway", Enum.RenderPriority.Camera.Value + 1, function(deltaTime)
	local MouseDelta = UserInputService:GetMouseDelta()

	Turn = Lerp(Turn, math.clamp(MouseDelta.X, -100, 100), (6 * deltaTime))

	Camera.CFrame = Camera.CFrame * CFrame.Angles(0, 0, math.rad(Turn))
end)

local function bobble()
	if humanoid.MoveDirection ~= Vector3.new() then
		local strength = humanoid.WalkSpeed / 1.2
		local shakes = math.sin(tick() * strength) / -70
		local shakec = math.cos(tick() * strength/2) / -70
		
		Camera.CFrame *= CFrame.Angles(math.rad(shakes),math.rad(shakec),0)
	else
		local strength = 1.5
		local shakes = math.sin(tick() * strength) / 120
		local shakec = math.cos(tick() * strength/2.5) / 120
		Camera.CFrame *= CFrame.Angles(math.rad(shakes),math.rad(shakec),0)
	end
end

RunService.RenderStepped:Connect(function()
	bobble()
end)

ive tried to make the sin and cos different but its not smooth enough

2 Likes

What precisely are you looking to make smoother? I see one issue where the bobble wont be continuous (when strength changes), but other than that, you are using tick() which is appropriate and should be perfectly smooth, and you are running it on RenderStepped (however, I was testing stuff, and RenderStepped was after the camera or something?). Maybe try running both functions using BindToRenderStep at a priority of Enum.RenderPriority.Camera.Value - 1 (instead of + 1), so just before the camera starts rendering. If you do +1, it will basically render on the next frame, which could make it less smooth

oh sorry its the lower script that does the bobbing

i say to make the running feel like actual running, you could smoothly increase the bobbing increment when running

1 Like

also consider using delta time, so the bobbing strength doesnt vary on fps

Using tick(), os.clock() or similar has the same effect as using deltaTime, since you are using time directly, it isn’t dependant on fps

I was talking about both, the one in RenderStepped, and the animation to turn the camera. I would put both of them in a BindToRenderStep with a priority of Enum.RenderPriority.Camera.Value - 1

1 Like
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")



local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera
local humanoid = LocalPlayer.Character.Humanoid
local Turn = 0

local Lerp = function(a, b, t)
	return a + (b - a) * t
end;

RunService:BindToRenderStep("CameraSway", Enum.RenderPriority.Camera.Value - 1, function(deltaTime)
	local MouseDelta = UserInputService:GetMouseDelta()

	Turn = Lerp(Turn, math.clamp(MouseDelta.X, -100, 100), (6 * deltaTime))

	Camera.CFrame = Camera.CFrame * CFrame.Angles(0, 0, math.rad(Turn))
	if humanoid.MoveDirection ~= Vector3.new() then
		local strength = humanoid.WalkSpeed / 1.2
		local shakes = math.sin(deltaTime * strength) / -70
		local shakec = math.cos(deltaTime * strength/2) / -70
		
		Camera.CFrame *= CFrame.Angles(math.rad(shakes),math.rad(shakec),0)
	else
		local strength = 1.5
		local shakes = math.sin(tick() * strength) / 120
		local shakec = math.cos(tick() * strength/2.5) / 120
		Camera.CFrame *= CFrame.Angles(math.rad(shakes),math.rad(shakec),0)
	end
end)

like this? it just goes to right when i walk

do i need to make that when delta time is higher the speed is gonan be higher too?

like multiplying/dividin or something like that to the strength

No, this

local shakes = math.sin(deltaTime * strength) / -70
local shakec = math.cos(deltaTime * strength/2) / -70

Doesn’t work, because delta time is the amount of time that passed since the last frame. So if your game is running at 60 frames per second, 1/60 seconds have passed since the last frame, that’s deltaTime. So if you do deltaTime * strength, this value is somewhat constant, so your wobble stops wobbling

If you want to use deltaTime, which can be useful for making increases in the strength smooth, (doing so while using tick() would be a bit mathy), you can do

local WobblePos = 0
RunService:BindToRenderStep("CameraSway", Enum.RenderPriority.Camera.Value - 1, function(deltaTime)
	local MouseDelta = UserInputService:GetMouseDelta()

	Turn = Lerp(Turn, math.clamp(MouseDelta.X, -100, 100), (6 * deltaTime))

	Camera.CFrame = Camera.CFrame * CFrame.Angles(0, 0, math.rad(Turn))

	-- WobblePos is a number that continuously increases, but the rate of increase depends on strength
	WobblePos += deltaTime * strength

	if humanoid.MoveDirection ~= Vector3.new() then
		local strength = humanoid.WalkSpeed / 1.2
		local shakes = math.sin(WobblePos) / -70
		local shakec = math.cos(WobblePos/2) / -70
		
		Camera.CFrame *= CFrame.Angles(math.rad(shakes),math.rad(shakec),0)
	else
		local strength = 1.5
		local shakes = math.sin(WobblePos) / 120
		local shakec = math.cos(WobblePos/2.5) / 120
		Camera.CFrame *= CFrame.Angles(math.rad(shakes),math.rad(shakec),0)
	end
end)

but if wobblepos is continously increases doesnt it bit too much fast after some thime?

yeah it just slows down everything

math.sin() is a periodic function, that means, math.sin(x) is equal to math.sin(2*math.pi + x) (and you can actually add 2pi any number of time, it wont change the result). So x being 0, or being 5 million doesn’t change how fast the wobble is, what affects that is how fast increases.

Same thing with math.cos(), cosine is very similar to sine, it’s basically just a function that is an offset of math.sin()

On desmos.com, you can look at the shape of a function:


The x (horizontal) axis is the number given to math.sin(). The y (vertical) axis is the number returned by math.sin()

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