Camera Bobbing doesnt work with different FPS

i have a camera bobbing script that works well other than the fact fps unlockers break it.

i know that im supposed to use delta time but i dont know how to put it in the script

code:

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local running = false

local camerabobcf = CFrame.new()
local cam = workspace.CurrentCamera
local Speed = 5
local ZAxis = .2
local YAxis = .15
running = false

game:GetService("RunService").Heartbeat:Connect(function(dt)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin(tick() * Speed + 1),
			0, 
			ZAxis * math.sin(tick() * Speed)) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end
	
	cam.CFrame = cam.CFrame
		* camerabobcf 

end)

hum.Running:Connect(function(speed)
	Speed = hum.WalkSpeed/1.1
	YAxis = hum.WalkSpeed/900
	ZAxis = hum.WalkSpeed/900
	if speed > 1 then
		running = true
	else
		running = false
	end
end)

For your sine computation, just multiply deltaTime by your speed, and that’s it really.

Doing this assures the rate of increase remains consistent between different frame rates.

local speed = 5
local sine = math.sin(speed*dt)
1 Like
local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local running = false

local camerabobcf = CFrame.new()
local cam = workspace.CurrentCamera
local speed = 5
local sine =math.sin(speed*dt)
local ZAxis = .2
local YAxis = .15
running = false

game:GetService("RunService").Heartbeat:Connect(function(dt)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin(tick() * speed + 1),
			0, 
			ZAxis * math.sin(tick() * speed)) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end
	
	cam.CFrame = cam.CFrame
		* camerabobcf 

end)

hum.Running:Connect(function(speed)
	speed = hum.WalkSpeed/1.1
	YAxis = hum.WalkSpeed/900
	ZAxis = hum.WalkSpeed/900
	if speed > 1 then
		running = true
	else
		running = false
	end
end)

Might have done this wrong lol

so this?

if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin(tick() * Speed + 1 * dt),
			0, 
			ZAxis * math.sin(tick() * Speed * dt)) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end

Yes that looks good, although I don’t think your use of tick() is necessary.

For some reason even with that code, its still different based off fps

I think RenderStepped is a better Event to connect to in this case since RenderStepped is not related to Physics but rather to fps ().

1 Like

Also using CFrame.identity is faster than CFrame.new()

1 Like

TRUE i totally forgot i was using heartbeat but even chaning to renderstepped doesnt fix it

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local running = false

local camerabobcf = CFrame.new()
local cam = workspace.CurrentCamera
local Speed = 5
local ZAxis = .2
local YAxis = .15
running = false

game:GetService("RunService").RenderStepped:Connect(function(dt)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin(tick() * Speed + 1 * dt),
			0, 
			ZAxis * math.sin(tick() * Speed * dt)) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end
	
	cam.CFrame = cam.CFrame
		* camerabobcf 

end)

hum.Running:Connect(function(speed)
	Speed = hum.WalkSpeed/1.1
	YAxis = hum.WalkSpeed/900
	ZAxis = hum.WalkSpeed/900
	if speed > 1 then
		running = true
	else
		running = false
	end
end)


It might be an issue with operator precedence, try this:


game:GetService("RunService").RenderStepped:Connect(function(dt)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin((tick() * Speed + 1 )*dt),
			0, 
			ZAxis * math.sin(tick() * Speed * dt)) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end
	
	cam.CFrame = cam.CFrame
		* camerabobcf 

end)

hum.Running:Connect(function(speed)
	Speed = hum.WalkSpeed/1.1
	YAxis = hum.WalkSpeed/900
	ZAxis = hum.WalkSpeed/900
	if speed > 1 then
		running = true
	else
		running = false
	end
end)

1 Like

still doesnt work, even so to the point where i had to make the speed variable very small
i think you should test this code in a baseplate so you can figure out this instead of positing code, me testing, it possibly not working
thanks

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local running = false

local camerabobcf = CFrame.new()
local cam = workspace.CurrentCamera
local Speed = .000000001
local ZAxis = .2
local YAxis = .15
running = false

game:GetService("RunService").RenderStepped:Connect(function(dt)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin((tick() * Speed )*dt),
			0, 
			ZAxis * math.sin(tick() * Speed * dt)) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end

	cam.CFrame = cam.CFrame
		* camerabobcf 

end)

hum.Running:Connect(function(speed)
	Speed = hum.WalkSpeed/2000.1
	YAxis = hum.WalkSpeed/900
	ZAxis = hum.WalkSpeed/900
	if speed > 1 then
		running = true
	else
		running = false
	end
end)

Only thing I can think of based on what I’m seeing is to get rid of the tick() calls, I think it’s local to the machine which may cause inconsistent results I’m not really sure.

That will also cause you to need to have speed set to something much higher.

I’ve never had an issue with this for me, that’s why I think it may be something with tick.

1 Like

removing the tick() and changing the values made it so there is no effect at all

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local running = false

local camerabobcf = CFrame.new()
local cam = workspace.CurrentCamera
local Speed = 1000
local ZAxis = 1000.2
local YAxis = 1000.15
running = false

game:GetService("RunService").RenderStepped:Connect(function(dt)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin((Speed )*dt),
			0, 
			ZAxis * math.sin(Speed * dt)) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end

	cam.CFrame = cam.CFrame
		* camerabobcf 

end)

hum.Running:Connect(function(speed)
	Speed = hum.WalkSpeed/1.1
	YAxis = hum.WalkSpeed/900
	ZAxis = hum.WalkSpeed/900
	if speed > 1 then
		running = true
	else
		running = false
	end
end)

You could use increment variables for both the Y and Z sine:

local xSine, zZine = 0, 0

xSine += math.sin(speed*dt)
zSine += math.sin(speed*dt)

--//apply sine

Roblox will roll out support for higher refresh rate in the future though for now unlockers will face issues like the one you faced. I’d simply advise you to assume everyone runs with the fixed rate (60).

Roblox barely runs as fast as their limit (60), on high end computers. I’d say the solution to your problem will be part of a big update that may come out via internal employees.

Some mobile devices may be capped at 30 FPS (or lower end PCs, who knows.) So nonetheless it is quite useful to take into account delta time when doing things that are tied to frame rate.

1 Like

Sure - however keep in mind rendering behaviour is altered regardless. We’re talking about an increased amounts of Renderstepped here. Physics may also suffer(?) even though it isn’t tied to rendering.

As of now, Roblox’s physics successfully prevents going behind time on the capped limit. Removing this limit severely impacts aspects of your Roblox Client and the server(?) to an extent. It’s not supported.

@C_Sharper this is the code im using, and still doesnt work with fps differences despite multiplying by the FPS, try this yourself in an empty baseplate and see if you could solve it:

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local running = false

local camerabobcf = CFrame.new()
local cam = workspace.CurrentCamera
local Speed = 15
local ZAxis = 0
local YAxis = 0
local XAxis = 0
running = false

game:GetService("RunService").RenderStepped:Connect(function(dt)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin(tick() * Speed )* dt/5.6,
			0, 
			XAxis * math.sin(tick() * Speed )* dt/5.6,
			0, 
			ZAxis * math.sin(tick() * Speed )* dt/5.6) -- intensity * math.sin(tick() * speed))
			,.1)
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end
	
	cam.CFrame = cam.CFrame
		* camerabobcf 

end)

hum.Running:Connect(function(speed)
	Speed = hum.WalkSpeed/1.1
	XAxis = hum.WalkSpeed/2
	YAxis = hum.WalkSpeed/2
	ZAxis = hum.WalkSpeed/2
	if speed > 1 then
		running = true
	else
		running = false
	end
end)

Still needs to be fixed , this is the updated code:

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local running = false

local camerabobcf = CFrame.new()
local cam = workspace.CurrentCamera
local Speed = 1.5
local ZAxis = 0
local YAxis = 0
local XAxis = 0
running = false

game:GetService("RunService").RenderStepped:Connect(function(FPS)

	if running then
		camerabobcf = camerabobcf:Lerp(CFrame.new() * CFrame.Angles(
			YAxis * math.sin(tick() * Speed )* (FPS/10),
			0, 
			XAxis * math.sin(tick() * Speed )* (FPS/10),
			0, 
			ZAxis * math.sin(tick() * Speed )* (FPS/10)) -- intensity * math.sin(tick() * speed))
			,.1) 
	else
		camerabobcf = camerabobcf:Lerp(CFrame.new(),.1) 
	end
	
	cam.CFrame = cam.CFrame
		* camerabobcf 
	--print(math.round(XAxis * math.sin(tick() * Speed )* FPS * 15))
end)

hum.Running:Connect(function(speed)
	Speed = hum.WalkSpeed/1.1
	XAxis = hum.WalkSpeed/1.5
	YAxis = hum.WalkSpeed/1.5
	ZAxis = hum.WalkSpeed/1.5
	if speed > 1 then
		running = true
	else
		running = false
	end
end)


Have you tried this answer from this post?

1 Like