How to make a FPS Counter

Hello. Today I’ll go step by step on How to make a FPS Counter.

First Step, you need to make a ScreenGui with a ‘TextLabel’ inside. Just like this.
DISCLAIMER: You do not need any text inside the TextLabel! The code changes it, which you can see in a few seconds.
image

Secondly, you need to add a ‘Local Script’ into the ‘Text Label’. Just like this.
image

Last Step, Copy and Paste this code into your Local Script.

local RS = game:GetService("RunService")
local frames = 0

RS.RenderStepped:Connect(function()
	frames = frames + 1
end)

while wait(1) do
	script.Parent.Text = frames .. " FPS"
	frames = 0
end

The code should look like this.
image

There! You have successfully created a Fps Counter.
It should look like this in the end.
image

Feel free to customize it, and please heart this post so others see this. :cool:

102 Likes

Seems good! I’ll make sure to use it in my next projects. I never thought it was this simple (No offence intended)

4 Likes

Glad I could help! Have a wonderful day :cool::cool:

4 Likes

cool, I will use it in my proj

3 Likes

Glad to hear that! Have a amazing day :happy3:

3 Likes

Quick little FYI, the frames = frames + 1 can be shortened to frames += 1 (does exactly the same thing but is shorter, and this feature is apart of Luau, doesn’t come standard with Lua).

Also wait(1) can be changed to task.wait(1), since task version of wait is more consistent with timings (and does not use the 30hz clock like what roblox used to have)

Other than that though I’ll have to keep this in mind, may use one day eventually.

16 Likes

Also, this is NOT a FPS counter. You’re just basically adding 1 frame and not using the delta time in order to find out how many frames took to render.

3 Likes

Thanks, very helpful. I used it in my game if thats ok? BloxyLiminal♟ - Roblox

4 Likes

Using 1 / deltaTime can basically be chalked up to an ‘approximation’, since it’s taking how long it took to render the last frame, and then assuming that is your frames per second, which makes absolutely no sense since that’s the results from only each frame, at that point just show frametime. The result of using 1 / dt show how inaccurate it is as well.

Comparitively, counting every frame that occurs in one second is probably the purest implementation you’ll ever get of an ‘FPS’ value, since literally it’s counting the frames that occur every second.

7 Likes

This wouldn’t be a community tutorial if you couldn’t use it anywhere

7 Likes

I never seen one module or script that adds 1 frame to the current frame count they have. Please show me an example.

2 Likes

This tutorial is that script, it adds one ‘frame’ every frame, then after a second it sets the text label to that value, then clears the value to count again.

Again, that is ‘frames per second’, 1 / deltaTime is just another way of representing frametime, not framerate or fps.

5 Likes

The thing is, it’s updating every second, not like when the event is fired it will deal with it. This is why this code exist and it still acts like one.

RunService.RenderStepped:Connect(function(dt)
    local fps = 1 / dt
    TextLabel.Text = str(math.ceil(fps))
end)
3 Likes

not like when the event is fired it will deal with it. This is why this code exist and it still acts like one.

I don’t know at all what this means, I’m assuming you’re trying to say that 1 / deltaTime can be used to show it every frame, and not just every second like counting?

Having it update the “”“framerate”"" every frame will result in some barely readable, inconsistent blur of a framerate, especially on TV’s or monitors that experience a lot of ghosting. Yet, counting the framerate every second and showing it that way is perfectly readable and is arguably more accurate to the end-user.

4 Likes

Your point is correct, however I still yet to see other scripters to follow that kind of code.

2 Likes

Thank you for that. If Im being honest, This will help with my Game’s Optimization.

2 Likes

Wouldn’t it be better to have an array of the DT’s over the last second then add them up divide by how many there are then put that as the fps instead of doing it based on one frame as that way it’d be more accurate as an fps counter and not just a frame time viewer

3 Likes

should look a little bit like this

local RunService = game:GetService("RunService")
local FrameQueue = table.create(60)

local function getTotalDT()
	local total = 0
	for index, dt in ipairs(FrameQueue) do
		total += 1/dt
	end
	total /= #FrameQueue
	return total
end

RunService.RenderStepped:Connect(function(dt)
	if #FrameQueue == 60 then
		table.remove(FrameQueue, 1)
	end
	table.insert(FrameQueue, dt)
	script.Parent.Text = math.floor(getTotalDT() * 10)/10
end)
2 Likes

What this code does is whenever the RenderStepped event of RunService is fired, we add the frames variable with 1. Now since RenderStepped fires multiple times a second, the frames variable would add according to the amount of times the RenderStepped event is fired. And then we set frames to 0 every 1 second since fps is Frames Per Second.

4 Likes

That is the average fps, not fps.

Average framerate isn’t really useful unless you include it with a standard fps counter, 0.1% lows, max, etc. Let alone replacing frames per second.

Edit: Also that code sample has a bit of an efficiency problem; you’re doing table.remove at the first element, which will cause all 59 other elements to perform a downwards shift, whereas you could just remove the top element (60) and no shifting will occur every frame and it still works the exact same.

2 Likes