My game decides to implode with bugs if I use a fps unlocker

Hello!

I am working on a little FPS project. I have only worked on it for a few days now but everything seemed fine. Until by friend tested it out on Roblox. He was using an FPS unlocker and everything broke. Should I limit the game’s FPS to 60? How would I do that? Is there a simple way to fix everything?

9 Likes

if you use RenderStepped or Stepped in a local script then that would be the reason since its runs faster if your fps is higher and slower if the fps is lower

1 Like

Would there be a way to make sure renderstep runs 60 times second?

1 Like

I don’t know for sure but there was something called artificial HB which would make some kind of limiting thing but I don’t know where to find it.

edit: maybe this post can help How can I make RenderStepped lock to a maximum of 60 FPS? - #10 by nooneisback

1 Like
local Game = game
local RunService = Game:GetService("RunService")

local Time = os.time()
local Frames = 0

local function OnRenderStep(Delta)
	if os.time() > Time then
		Time = os.time()
		Frames = 0
	end
	Frames += 1
	if Frames > 60 then return end
	--Do code here.
end

RunService.RenderStepped:Connect(OnRenderStep)

This will prevent the function’s execution past sixty frames in a single second.

(post deleted by author)

1 Like

(post deleted by author)

What?No, this is terrible practice.

This is a baseless claim, it’s just a way of capping the event loop to sixty executions per second, you seem to have omitted the fact that the ‘Delta’ parameter can be used in the function’s body.

1 Like

(post deleted by author)

Second of all, yes it is a terrible practice, you should never assume the client is ever running at one specific framerate.

Another erroneous claim, the implementation does not assume that the client has a particular framerate, it’s just ignoring frames past the hard-coded sixty frame cap.

1 Like

(post deleted by author)

So you’re gonna completely ignore if someone is below 60FPS, which will cause them to experience everything at a slower rate?

The ‘Delta’ parameter is there for a reason, are you unaware of its use?
https://developer.roblox.com/en-us/api-reference/event/RunService/RenderStepped

You should ALWAYS use delta for any number-specific animations or frame-dependent actions.

The implementation does?

I’ve been programming on Roblox for 6 years.

2 Likes

This solution will allow your friend to keep using his fps-unblocker, without it being capped.

For example, take this piece of code, that moves a part 10 studs in the Y direction, across 20 frames:

local runService = game:GetService("RunService")

local camera = workspace.CurrentCamera
local part = workspace.Part

part.Position = Vector3.new(0, 20, 0)
local targetCameraPosition = Vector3.new(-20, 25, 0)
camera.CameraType = Enum.CameraType.Scriptable
camera.CFrame = CFrame.new(targetCameraPosition, part.Position) 

local iterations = 0
local maxIterations = 20

wait(2) --Studio takes some time to load into client mode, so don't do it right away

runService.RenderStepped:Connect(function(deltaTime)
	if iterations < maxIterations then
		iterations += 1
		part.Position += Vector3.new(0, 0.5, 0)
	end
	camera.CFrame = CFrame.new(targetCameraPosition, part.Position) 
end)

This is what this code looks like at 24 FPS:

At 60 FPS:

At 144 FPS:

What you’ll notice is, as frame rate increases, the animation speed also increases. This is because there is less time between frames. There will also be cases where players will have framerates below 60FPS, in this case, it is going to cause animations to be slower for them, which will make the user experience worse.

The good thing is, every frame an argument is passed through RenderStepped, called Delta, what this tells us is the time that it took between the last frame and the current frame. This is also called Step, or shortened to s in some scripts. For a player who’s running at 24 FPS this will be approximately 1/24th of a second or 0.04166..s, for a player who’s running at 60 FPS it will be approximately 1/60th of a second, or 0.0166..s, and at 144 FPS, it will be approximately 0.006944...s. This will be useful to you as a programmer, as it essentially tells you what fraction of a second has passed, and you can adjust how fast animations happen as a result.

You can read more here:

What this means is, if you wanted to move a part 10 studs, within 1/3rd of a second, you’d say 10 studs * (delta / 1/3 seconds), which will move the part the correct amount within the specified time, so that no matter what framerate the player is on, it will look smooth, and will have exactly the same speed.

Here is some example code, which utilizes the Delta argument:

local runService = game:GetService("RunService")

local camera = workspace.CurrentCamera
local part = workspace.Part

part.Position = Vector3.new(0, 20, 0)
local targetCameraPosition = Vector3.new(-20, 25, 0)
camera.CameraType = Enum.CameraType.Scriptable
camera.CFrame = CFrame.new(targetCameraPosition, part.Position) 

local studsToMove = 10
local timeToComplete = 3

wait(2) --Studio takes some time to load into client mode, so don't do it right away

local studsMoved = 0
runService.RenderStepped:Connect(function(deltaTime)
	if studsMoved <= studsToMove then
		local targetStudsToMove = math.min(
			studsToMove - studsMoved, 
			studsToMove * (deltaTime / timeToComplete)
		)
		part.Position += Vector3.new(0, targetStudsToMove, 0)
		studsMoved += targetStudsToMove
	end
	camera.CFrame = CFrame.new(targetCameraPosition, part.Position) 
end)

This is what it looks like at 5 FPS (for exaggeration):

This is what it looks like at 60 FPS:

This is what it looks like at 144 FPS:

You’ll notice that they look exactly the same speed regardless of framerate.
This is the way to go.

Please do not listen to other advice to cap the framerate. It is bad practice.

If you need any specific advice on how to handle delta or frame times, do not hesitate to PM me. I’ll always be willing to be a helping hand .

6 Likes
local part = workspace.Part

image
Use WaitForChild to wait for instances to replicate to the client.

camera.CFrame = CFrame.new(targetCameraPosition, part.Position) 

Use the CFrame.lookAt constructor, it’s more readable and expects two ‘Vector3’ values.
https://developer.roblox.com/en-us/api-reference/datatype/CFrame

wait(2)

The wait global function is deprecated (it throttles), use the task library function of the same name.
https://developer.roblox.com/en-us/api-reference/lua-docs/task
I’d argue that the arbitrary wait isn’t even necessary.

part.Position += Vector3.new(0, targetStudsToMove, 0)

This should be a CFrame property assignment as they are considerably more performant.

part.CFrame *= CFrame.new(0, targetStudsToMove, 0)

A minor nitpick but connect a locally defined function rather than an anonymous one.

1 Like

Did you seriously recommend someone to frameskip their way out framerate instability? These aren’t the 90s where you needed a dedicated turbo button to prevent your computer from running too fast. This is something even Roblox engine developers warn against, though I won’t go digging for 5 year old posts.

3 Likes

This is honestly the worst practice I can think of related to this problem. Setting an fps lock is a horrible idea

1 Like

Setting an fps lock is a horrible idea

Why? It’s merely a way of punishing users that inject .dll files in order to increase their framerate without outright kicking/banning them.

1 Like

But it is also a HUGE disadvantage for low fps users

1 Like

Disagree with your method of locking FPS, but you sending a Wikipedia article of the Dunning-Kruger effect just made my whole day in response to that quote. That was the best thing I’ve seen today.

Truly, thank you

2 Likes

Also, chill out. You come across as very ignorant and condescending with the whole connotation of your initial statements.

I’m sure I don’t have to explain this to someone with your 6 years of expertise but you’ll have a harder time having people listen to you when you appear as such.

1 Like