Мой код вычисляет средний FPS. Каждые 0,4 секунды он обновляет текст FPS. Каждые 2 секунды сбрасывает средний FPS. Мне нужно рассчитать точный и плавный FPS (чтобы любые временные всплески были устранены). Так будет ли этот код счетчика FPS соответствовать моим требованиям?
[RequireComponent(typeof(TMP_Text))]
public class FpsCounter : MonoBehaviour
{
private struct AverageFloat
{
public float Average => _value / _count;
private float _value;
private int _count;
public void Add(float number)
{
_value += number;
_count++;
}
public void Reset()
{
_value = 0f;
_count = 0;
}
}
[SerializeField] private float _averageValueCollectionTime = 2f;
[SerializeField] private float _refreshFrequency = 0.4f;
private float _timeSinceFpsReset = 0f;
private float _timeSinceUpdate = 0f;
private AverageFloat _fpsValue;
private TMP_Text _text;
private void Start()
{
_text = GetComponent<TMP_Text>();
}
private void Update()
{
if (_timeSinceFpsReset > _averageValueCollectionTime)
{
_timeSinceFpsReset = 0;
_fpsValue.Reset();
}
_fpsValue.Add(1f / Time.unscaledDeltaTime);
_timeSinceFpsReset += Time.deltaTime;
if (_timeSinceUpdate < _refreshFrequency)
{
_timeSinceUpdate += Time.deltaTime;
return;
}
int fps = Mathf.RoundToInt(_fpsValue.Average);
_text.text = fps.ToString();
_timeSinceUpdate = 0f;
}
}
Я тогда не знал :/
Вы можете использовать InvokeRepeating , чтобы сбросить/обновить количество средних FPS, в дополнение к Time.frameCount, чтобы получить количество кадров.
Итак... Лучше считать FPS с экспоненциально взвешенной скользящей средней. Это решение дает более точные и плавные результаты.
[RequireComponent(typeof(TMP_Text))]
public class FpsCounter : MonoBehaviour
{
[SerializeField] [Range(0f, 1f)] private float _expSmoothingFactor = 0.9f;
[SerializeField] private float _refreshFrequency = 0.4f;
private float _timeSinceUpdate = 0f;
private float _averageFps = 1f;
private TMP_Text _text;
private void Start()
{
_text = GetComponent<TMP_Text>();
}
private void Update()
{
// Exponentially weighted moving average (EWMA)
_averageFps = _expSmoothingFactor * _averageFps + (1f - _expSmoothingFactor) * 1f / Time.unscaledDeltaTime;
if (_timeSinceUpdate < _refreshFrequency)
{
_timeSinceUpdate += Time.deltaTime;
return;
}
int fps = Mathf.RoundToInt(_averageFps);
_text.text = fps.ToString();
_timeSinceUpdate = 0f;
}
}
_expSmoothingFactor должен быть установлен от 0 до 1. Он определяет степень применения сглаживания. Значение 0,9 является наиболее оптимальным (чем выше значение, тем больше сглаживание).
Ну... это соответствует вашим требованиям? Звучит как вопрос Code Review Stack Exchange.