Unity杂文——FPS计算并显示
自制游戏FPS显示工具
在游戏开发中,FPS(Frames Per Second)是一个非常重要的指标,它可以反映出游戏的流畅度和性能。为了帮助开发者更好地优化游戏性能,我们可以使用一个自制的游戏FPS显示工具,实时显示当前的帧率。
代码
以下是自制的游戏FPS显示工具的代码实现:
public class FPSUtils : MonoBehaviour
{
#region 实例化
private static FPSUtils s_FPS = null;
/// <summary>
/// 实例化一个FPS单位
/// </summary>
/// <param name="parent"></param>
public static void CreateInstance(GameObject parent = null)
{
if (s_FPS != null) return;
var go = new GameObject("FPS");
s_FPS = go.AddComponent<FPSUtils>();
if (null == parent)
{
DontDestroyOnLoad(go);
}
else
{
go.SetParent(parent);
go.SetAsFirstSibling();
}
}
/// <summary>
/// 销毁一个FPS单位
/// </summary>
public static void DestroyInstance()
{
if (null != s_FPS)
{
Destroy(s_FPS.gameObject);
s_FPS = null;
}
}
#endregion
#region FPS统计
/// <summary>
/// 是否显示FPS
/// </summary>
private bool m_IsShowFPS = true;
/// <summary>
/// 帧数计算刷新时间(s)
/// </summary>
private const float m_ShowTime = 1f;
/// <summary>
/// 当前时间
/// </summary>
private float m_CurTime = 0f;
/// <summary>
/// 当前帧数
/// </summary>
private static int m_Frames = 0;
/// <summary>
/// 临时FPS
/// </summary>
private int m_TempFPS = 0;
/// <summary>
/// 帧数变化比较容忍度
/// </summary>
private const int TOLERANCE = 5;
/// <summary>
/// 当前FPS
/// </summary>
private int m_CurFPS;
/// <summary>
/// 当前显示的帧数
/// </summary>
private int m_CurShowFPS;
/// <summary>
/// 品质当前时间
/// </summary>
private float m_QualityCurTime = 0f;
/// <summary>
/// 品质的容忍度
/// </summary>
private const int m_TotalTime = 10;
/// <summary>
/// 帧数容忍度
/// </summary>
private const int m_MaxFrameCount = 200;
/// <summary>
/// 最小FPS容忍度
/// </summary>
private const int m_MinFPS = 10;
/// <summary>
/// 当前最小帧数
/// </summary>
private int m_CurMinFrmCount = 0;
private void Update()
{
m_CurTime += Time.unscaledDeltaTime;
m_Frames++;
m_CurFPS = (int)(1.0f / Time.unscaledDeltaTime);
if (m_CurTime >= m_ShowTime)
{
m_CurShowFPS = (int)(m_Frames / m_CurTime);
if (Math.Abs(m_CurShowFPS - m_TempFPS) > TOLERANCE)
{
m_TempFPS = m_CurShowFPS;
}
m_CurTime = 0;
m_Frames = 0;
}
}
private void FixedUpdate()
{
m_QualityCurTime += Time.unscaledDeltaTime;
if (m_QualityCurTime >= m_TotalTime)
{
m_CurMinFrmCount = 0;
m_QualityCurTime = 0;
}
if (m_CurFPS >= m_MinFPS) return;
m_CurMinFrmCount++;
if (m_CurMinFrmCount > m_MaxFrameCount)
{
//检测到帧率过低,可以做切换品质的功能
}
}
/// <summary>
/// 绘制FPS
/// </summary>
private void OnGUI()
{
if (m_IsShowFPS)
{
var fpsStr = $"FPS:{m_CurShowFPS}";
GUI.Label(new Rect(0, 0, 100, 20), fpsStr);
}
}
#endregion
}
代码解释
以上代码中,FPSUtils类继承自MonoBehaviour,用于实现FPS统计和显示。
首先,定义了一个静态的CreateInstance方法,用于创建一个FPSUtils实例。在该方法中,首先判断是否已经存在一个FPSUtils实例,如果存在则直接返回。如果不存在,则创建一个新的GameObject对象,并将FPSUtils组件添加到该对象上。如果指定了parent参数,则将新创建的对象设置为该parent对象的第一个子对象,否则将其设置为不会被销毁的对象。
然后,定义了一个静态的DestroyInstance方法,用于销毁FPSUtils实例。在该方法中,首先判断是否存在FPSUtils实例,如果存在则销毁该实例,并将其设置为null。
接下来,定义了一些用于FPS统计的变量,包括是否显示FPS、帧数计算刷新时间、当前时间、当前帧数、临时FPS、帧数变化比较容忍度、当前FPS、当前显示的帧数、品质当前时间、品质的容忍度、帧数容忍度、最小FPS容忍度、当前最小帧数等。
然后,在Update方法中,每帧更新当前时间、帧数和当前FPS。如果当前时间超过了帧数计算刷新时间,则计算当前显示的帧数,并将临时FPS设置为当前显示的帧数。在计算当前显示的帧数时,如果当前显示的帧数与临时FPS的差值超过了帧数变化比较容忍度,则将临时FPS设置为当前显示的帧数,并将当前时间和帧数重置为0。
在FixedUpdate方法中,每帧更新品质当前时间和当前最小帧数。如果当前FPS大于等于最小FPS,则直接返回。如果当前FPS小于最小FPS,则将当前最小帧数加1。如果当前最小帧数超过了帧数容忍度,则可以做一些切换品质的功能。
最后,在OnGUI方法中,如果需要显示FPS,则绘制当前显示的帧数。