【问题标题】:My FPS Counter is in-accurate any ideas why?我的 FPS 计数器不准确,为什么?
【发布时间】:2015-10-28 17:23:28
【问题描述】:

当我开始我的游戏时,它保持在 95-101 左右的快速变化,介于所有这些数字之间。但是当我打开统计栏时,我得到了 200 和 300 的上限

所以想知道为什么这对 c# 来说仍然是新的,所以对我来说轻松点,哈哈。这是代码 一如既往地提前感谢^_^。

float deltaTime = 0.0f;

void Update() 
{
    deltaTime += (Time.deltaTime - deltaTime) * 0.1f;
}

void OnGUI()
{
    int w = Screen.width, h = Screen.height;

    GUIStyle style = new GUIStyle ();

    Rect rect = new Rect (0, 0, w, h * 2 / 100);
    style.alignment = TextAnchor.UpperRight;
    style.fontSize = h * 2 / 100;
    style.normal.textColor = new Color (255.0f, 255.0f, 255.0f, 1.0f);
    float msec = deltaTime * 1000.0f;
    float fps = 1f / deltaTime;
    string text = string.Format ("({1:0.} fps)", msec, fps);
    GUI.Label (rect, text, style);
    }
}

【问题讨论】:

    标签: c# unity3d frame performancecounter frame-rate


    【解决方案1】:

    为了显示有意义的 FPS 速率,您需要测量在恒定时间段内渲染了多少帧,例如一秒。然后只有在那段时间之后,您才会在屏幕上显示计算值。这将提供 每秒平均帧数,而不是 每秒瞬时帧数,后者在大多数情况下并不是特别有用,因为它会导致值大幅波动.

    代码

    首先定义一些字段:

    DateTime _lastTime; // marks the beginning the measurement began
    int _framesRendered; // an increasing count
    int _fps; // the FPS calculated from the last measurement
    

    然后在您的渲染方法中增加_framesRendered。您还可以检查自周期开始以来是否已经过了一秒:

    void Update()
    {
        _framesRendered++;
    
        if ((DateTime.Now - _lastTime).TotalSeconds >= 1)
        {
            // one second has elapsed 
    
            _fps = _framesRendered;                     
            _framesRendered = 0;            
            _lastTime = DateTime.Now;
        }
    
        // draw FPS on screen here using current value of _fps          
    }
    

    跨技术

    需要指出的是,上面的代码没有特别使用 Unity,但仍然相当准确,并且与 DirectX 等许多框架和 API 兼容; OpenGL; XNA; WPF 甚至 WinForms。

    当我开始我的游戏时,它保持在 95-101 左右的快速变化,介于所有这些数字之间。但是当我打开统计栏时,我得到了 200 和 300 的上限

    华硕 VG248QE 是 1ms,它可以做的最大值是 144Hz,所以你不太可能得到“上 200 的低 300”。在非 GSYNC 显示器上关闭 VSYNC 时,FPS 毫无意义。你的 VSYNC 开启了吗?

    【讨论】:

    • 关于你应该绘制 _fps 的值的那一刻,它应该在一秒钟后的条件内。
    • @DanielV 不完全,_fps 的值需要在每一帧中绘制(因此在if 之外但_fps 的确定只能得到更新每秒一次。确实,第一秒它会显示0。如果我们愿意,我们可以在第一秒过去之前不绘制任何东西以使其更整洁。:)
    • 啊!你有一点,但在第一秒之后,价值更准确
    • 我正在搜索每秒计算请求,但不喜欢任何答案。然后我想寻找 FPS,因为那里有更多的游戏玩家。好东西+1
    【解决方案2】:

    OnGUI 函数每帧调用两次(有时更多)。您正在 OnGUI 中计算“FPS”,因此它几乎永远不会准确。

    定义:

    deltaTime += (Time.deltaTime - deltaTime) * 0.05f;
    

    将使您的 FPS 值最接近真实值,但如果您在 OnGUI 方法上计算它将不准确。

    我猜(不确定)你应该使用FixedUpdate() 而不是OnGUI() 来计算你的FPS。 (如果你使用 FixedUpdate,你也不需要改变你的 deltaTime 乘以 0.05f)

    【讨论】:

      【解决方案3】:

      在 Unity 中,FPS 相当于 1 秒内出现的Updates 的数量。这是因为Update()Time.deltaTime 秒被调用一次。

      InvokeRepeating 方法

      您也可以使用InvokeRepeating 来实现您自己的 FPS 计数器,同时只使用整数,如下所示:

      private int FrameCounter = 0;
      private int Fps = 0;
      
      void Start() 
      {
          InvokeRepeating("CountFps", 0f, 1f);
      }
      
      void Update()
      {
          FrameCounter++;
      }
      
      private void CountFps()
      {
          Fps = FrameCounter;
          FrameCounter = 0;
      }
      

      然后只需在OnGUI() 方法中显示Fps 变量。使用此方法,您的Fps 值将每秒更新一次;如果您想要更频繁的更新,请更改 InvokeRepeating 调用的最后一个参数,然后相应地调整 Fps 计算。

      但是请注意,InvokeRepeating 考虑了Time.timeScale,例如如果您使用Time.timeScale = 0f; 暂停游戏,计数器将停止更新,直到您取消暂停游戏。

      FixedUpdate 方法

      另一种方法是在 FixedUpdate() 方法中计算 FPS,而不是 OnGUI()Update()。这会在每 Time.fixedDeltaTime 秒被调用一次,无论如何都是一样的。 Time.fixedDeltaTime 的值可以通过菜单Edit->Project Settings->Time,项目Fixed Timestep 为项目全局设置。

      在这种情况下,您将以相同的方式计算帧数(在 Update 中),但在 FixedUpdate 中更新您的 FPS 计数器 - 这与使用 InvokeRepeating("CountFps", 0f, 0.02f) 调用您自己的方法基本相同(0.02f 是一个典型的Time.fixedDeltaTime 值,但这取决于您的项目设置,如上所述)。

      结论

      大多数时候,您不需要经常更新显示的 FPS,所以我个人喜欢使用 InvokeRepeating 方法和 1 秒间隔。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-17
        • 1970-01-01
        • 2012-12-28
        • 1970-01-01
        相关资源
        最近更新 更多