如何高效的评估游戏帧率稳定性

如何高效的评估游戏帧率稳定性:99 percentile FPS

using System.Collections;
using System.Collections.Generic;
using Unity.Profiling;
using UnityEngine;

/// <summary>
/// 99 percentile FPS非常好理解
/// 假设当前我们观察到游戏的平均帧率是 214 FPS,而 99 percentile FPS 是 114 FPS,那么我们获得直观的信息
/// 就是“在统计区间内,99%的情况下玩家可以获得 >= 114 FPS 的游戏体验,只有 1% 的情况下低于 114 FPS”
/// 减少卡顿的优化目标也非常明确:99 percentile FPS 尽量高
/// </summary>
public class FPSPercentile99 : MonoBehaviour
{
    public int FPS3;
    public int FPS99;

    public void Start()
    {
        InitFPS99Percentile();
    }

    public void Update()
    {
        UpdateFPS99Percentile(Time.deltaTime);
    }

    public void OnGUI()
    {
        //设置GUI样式
        GUIStyle style = new GUIStyle();
        style.fontSize = 50;
        style.normal.textColor = Color.white;

        GUI.Label(new Rect(10, 10, 100, 30), "FPS3: " + FPS3.ToString(), style);
        GUI.Label(new Rect(10, 100, 100, 30), "FPS99: " + FPS99.ToString(), style);
    }

    #region FPS 99 percentile

    // 统计区间3秒
    private static float _FPS99_INTERVAL = 3.0f;
    private static int _FPS99_RINGBUF_SIZE = (int)(2000 * _FPS99_INTERVAL);
    private static int _FPS99_MIN_FRAMERATE = 20;
    private static int _FPS99_MAX_FRAMERATE = 150;
    private static int[] _fps99_ringbuf = new int[_FPS99_RINGBUF_SIZE];
    private static float[] _fps99_timestamp = new float[_FPS99_RINGBUF_SIZE];
    private static int _fps99_h = 0;
    private static int _fps99_t = 0;
    private static int[] _fps99_count = new int[200];
    private static float _lastTimeStamp = 0f;

    void InitFPS99Percentile()
    {
        for (int i = 0; i < _FPS99_RINGBUF_SIZE; i++)
        {
            _fps99_ringbuf[i] = 0;
            _fps99_timestamp[i] = 0;
        }

        for (int i = _FPS99_MIN_FRAMERATE; i <= _FPS99_MAX_FRAMERATE; i++)
            _fps99_count[i] = 0;

        _fps99_h = _fps99_t = 0;

        _lastTimeStamp = 0f;
    }

    private static ProfilerMarker _UpdateFPS99PercentileMarker = new ProfilerMarker("UpdateFPS99Percentile");
    void UpdateFPS99Percentile(float deltaTime)
    {
        using (_UpdateFPS99PercentileMarker.Auto())
        {
            //adjust tail
            float tm = Time.realtimeSinceStartup;
            while (_fps99_t != _fps99_h && _fps99_timestamp[_fps99_t] < tm - _FPS99_INTERVAL)
            {
                int last = _fps99_ringbuf[_fps99_t];
                last = Mathf.Clamp(last, _FPS99_MIN_FRAMERATE, _FPS99_MAX_FRAMERATE);
                _fps99_count[last]--;
                _lastTimeStamp = _fps99_timestamp[_fps99_t];
                _fps99_t = (_fps99_t + 1) % _FPS99_RINGBUF_SIZE;
            }

            //adjust head,应该不会出现一秒大于2000fps吧
            int fps = (int)Mathf.Round(1.0f / (deltaTime + 0.000001f));
            fps = Mathf.Clamp(fps, _FPS99_MIN_FRAMERATE, _FPS99_MAX_FRAMERATE);

            _fps99_count[fps]++;
            _fps99_ringbuf[_fps99_h] = fps;
            _fps99_timestamp[_fps99_h] = tm;
            _fps99_h = (_fps99_h + 1) % _FPS99_RINGBUF_SIZE;

            // calculate avg framerate in range
            int interval_count = (_fps99_h + _FPS99_RINGBUF_SIZE - _fps99_t) % _FPS99_RINGBUF_SIZE;
            float interval_tm = tm - _lastTimeStamp;
            float avgfps = interval_count / (interval_tm + 0.000001f);
            FPS3 = (int)avgfps;

            // calculate fps 99
            float limit = interval_count * 0.01f;
            int low = _FPS99_MIN_FRAMERATE;
            int high = _FPS99_MIN_FRAMERATE;
            int rank = 0;

            for (int i = _FPS99_MIN_FRAMERATE; i <= _FPS99_MAX_FRAMERATE; i++)
            {
                if (_fps99_count[i] == 0) continue;
                if (rank + _fps99_count[i] >= limit)
                {
                    high = i;
                    break;
                }

                rank += _fps99_count[i];
                low = i;
            }

            //处理极端情况,碰到的第一个非0帧率就超过limit了
            low = rank == 0 ? high : low;

            int fps99 = (int)(Mathf.Lerp(low, high, (limit - rank) * (high - low)));
            FPS99 = fps99;
        }
    }
    #endregion
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值