我的FPS计数器是不准确的任何想法为什么?

时间:2015-08-05 19:10:25

标签: c# unity3d frame performancecounter frame-rate

当我启动游戏时,它会在所有这些数字之间保持在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);
    }
}

3 个答案:

答案 0 :(得分:2)

为了显示有意义的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,同时仍然相当准确,并且与许多框架和API(如DirectX)兼容; OpenGL的; XNA; WPF甚至WinForms。

  

当我启动游戏时,它会在所有这些数字之间保持在95-101左右快速变化..但是当我打开统计数据栏时,我得到了200以上的低300&#39 ; S

华硕VG248QE是1毫秒,它可以做的最大值是144赫兹所以你不太可能得到#200;高200的低300"。在非GSYNC监视器上关闭VSYNC时,FPS无意义。你的VSYNC开启了吗?

答案 1 :(得分:0)

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

定义:

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

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

我猜(不确定)您应该使用FixedUpdate()代替OnGUI()来计算您的FPS。 (如果使用FixedUpdate,也不需要将deltaTime更改为乘以0.05f)

答案 2 :(得分:0)

在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;
}

然后只需在Fps方法中显示OnGUI()变量。使用此方法,您的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计数器 - 这与使用{{1}调用您自己的方法基本相同(InvokeRepeating("CountFps", 0f, 0.02f)是典型的0.02f值,但这取决于您上面的项目设置。

<强>结论

大多数情况下,您不需要经常更新显示的FPS,因此我个人喜欢使用Time.fixedDeltaTime方法和1秒间隔。