- Home /
Accurate Frames Per Second Count
What's the best or most accurate way to get a FPS count? Should the frameCount and Time.time division be put in Update or LateUpdate, or does it matter?
Answer by Bunny83 · May 13, 2011 at 11:11 AM
Update or LateUpdate doesn't matter. The question is what do you mean by most accurate. frames per second is never a constant value, it can fluctuate even within one second.
var fps = 1.0/Time.deltaTime;
that gives you the current FPS but that will change every frame.
You could smooth the delta, but it will be less accurate.
var deltaTime = 0.0;
var fps = 0.0;
function Update()
{
deltaTime += Time.deltaTime;
deltaTime /= 2.0;
fps = 1.0/deltaTime;
}
If you want to display the value, the best way is to accumulate the frames yourself and calculate the FPS in fix time steps.
var frameCount = 0;
var nextUpdate = 0.0;
var fps = 0.0;
var updateRate = 4.0; // 4 updates per sec.
function Start()
{
nextUpdate = Time.time;
}
function Update()
{
frameCount++;
if (Time.time > nextUpdate)
{
nextUpdate += 1.0/updateRate;
fps = frameCount * updateRate;
frameCount = 0;
}
}
edit
Added a little bit more accuracy to the second solution (like mentioned in the comments) and here's another one that's probably the "most" accurate.
var frameCount = 0;
var dt = 0.0;
var fps = 0.0;
var updateRate = 4.0; // 4 updates per sec.
function Update()
{
frameCount++;
dt += Time.deltaTime;
if (dt > 1.0/updateRate)
{
fps = frameCount / dt ;
frameCount = 0;
dt -= 1.0/updateRate;
}
}
A $$anonymous$$or bugfix to the last solution above. To ensure you don't lose 1 frame of precision on each update tick, replace:
nextUpdate = Time.time + 1.0/updateRate;
with:
nextUpdate += 1.0/updateRate;
@a1studmuffin:
Yes, good spot. I usually do it that way ;)
Well if you do this you should initialize nextUpdate in Start with Time.time. Or if you (for some reason) have disabled the script in the beginning and enable it after lets say 10$$anonymous$$ while in the game it would take 2400 frames (about 40 seconds @ 60 fps) until the correct value is shown and nextUpdate would catch up with the current time. That's why you have to be careful with pure incremental values ;)
Looking at this now it's actually not very precise ;) Of course it shows you the actual frame count within this time period but doesn't take fractions into account. So the number will always be a whole number. It's probably better to accumulate deltaTime over a certain timespan and calculate the FPS from the dt value.
I'll fix the second add a third solution ;)
After all this time I still don't know why
dt -= 1.0/updateRate;
isn't
dt = 0;
He's using this:
dt -= 1.0/updateRate
...so he doesn't lose the fractional amount of time that has past. For instance, dt could be anything higher than 0.25, in his example:
if (dt > 1.0/updateRate)
If dt was say, 0.35, then it's 0.1 over 0.25, and he doesn't want to lose that accuracy every update.
This method will fail in cases where the frame lasts 0.5 or more seconds longer per frame, but at that point you know you have some performance issues so the counter is still doing its job :D.
The framerate is lower than the built in stats, anybody else finding this? Also which one is more accurate?
I recommend to use unscaledDeltaTime or it will not show the FPS while pause menu.
Here is my final script, just add it in your scene, add a Text reference and you FPS is displayed formatted.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// This script calculate the current fps and show it to a text ui.
/// </summary>
public class UiDisplayFps : $$anonymous$$onoBehaviour
{
public string formatedString = "{value} FPS";
public Text txtFps;
public float updateRateSeconds = 4.0F;
int frameCount = 0;
float dt = 0.0F;
float fps = 0.0F;
void Update()
{
frameCount++;
dt += Time.unscaledDeltaTime;
if (dt > 1.0 / updateRateSeconds)
{
fps = frameCount / dt;
frameCount = 0;
dt -= 1.0F / updateRateSeconds;
}
txtFps.text = formatedString.Replace("{value}", System.$$anonymous$$ath.Round(fps, 1).ToString("0.0"));
}
}
Answer by CHPedersen · May 13, 2011 at 11:05 AM
Do you mean after the project has been built? If you want to just see the FPS, you can click the "Stats"-button while the program runs in the editor. It displays the FPS.
FPS Graph works on mobile, it will give you the frame rate and other performance indicators. The framerate in the stats window is not always reliable as explained on this forum page.
Answer by gabearts · Apr 21, 2020 at 10:02 PM
That was an awesome insight and wanted to share my own version, based off the same thing but another way to approach it with refresh interval.
public class FPSCounter : MonoBehaviour {
public float timer, refresh, avgFramerate;
string display = "{0} FPS";
private Text m_Text;
private void Start()
{
m_Text = GetComponent<Text>();
}
private void Update()
{
float timelapse = Time.smoothDeltaTime;
timer = timer <= 0 ? refresh : timer -= timelapse;
if(timer <= 0) avgFramerate = (int) (1f / timelapse);
m_Text.text = string.Format(display,avgFramerate.ToString());
}
}
Answer by Desertleaf · Mar 19, 2021 at 03:45 PM
None of these are counting frames but rather a float value within the time spent during the update.
These solutions are completely false and made up.
The correct solution would be to look into .Net API and getting the GPU’s actual frame completion. Once the frame is completed, you compare that to the time spent.
Answer by DarkGate · Jul 03, 2021 at 09:49 AM
Bit late to the party, below is the solution provided in the Unity's Standard Assets.
using System;
using UnityEngine;
using UnityEngine.UI;
namespace UnityStandardAssets.Utility {
[RequireComponent(typeof(Text))]
public class FPSCounter : MonoBehaviour {
const float fpsMeasurePeriod = 0.5f;
private int m_FpsAccumulator = 0;
private float m_FpsNextPeriod = 0;
private int m_CurrentFps;
const string display = "{0} FPS";
private Text m_Text;
private void Start() {
m_FpsNextPeriod = Time.realtimeSinceStartup + fpsMeasurePeriod;
m_Text = GetComponent<Text>();
}
private void Update() {
// measure average frames per second
m_FpsAccumulator++;
if (Time.realtimeSinceStartup > m_FpsNextPeriod) {
m_CurrentFps = (int)(m_FpsAccumulator / fpsMeasurePeriod);
m_FpsAccumulator = 0;
m_FpsNextPeriod += fpsMeasurePeriod;
m_Text.text = string.Format(display, m_CurrentFps);
}
}
}
}
Your answer
Follow this Question
Related Questions
Framerate drops and Camera.render is high -1 Answers
Framerate drops when I preview my game, what is particleSystem.renderSingle in profiler? 0 Answers
Android lag 1 Answer
How to render severals cameras at differents Frame Rate ? 2 Answers
Why CPU waits for GPU when there is not much work on GPU? 0 Answers