Unity杂文——FPS计算并显示

2023-10-02  本文已影响0人  脸白

原文地址

自制游戏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,则绘制当前显示的帧数。

上一篇 下一篇

猜你喜欢

热点阅读