XNA/MonoGame:获取每秒帧数

Jef*_*eff 10 c# xna frame-rate monogame

我试图获得我游戏的当前FPS,但是我只能找到每秒更新FPS变量的方法.例如https://github.com/CartBlanche/MonoGame-Samples/blob/master/Draw2D/FPSCounterComponent.cshttp://www.david-amador.com/2009/11/how-to-do-a-xna -fps计数器/

有没有办法持续更新FPS标签?

cra*_*mes 26

这是我刚才写的FPS计数器课程.您应该能够将其放入代码中并按原样使用它.

public class FrameCounter
{
    public FrameCounter()
    {
    }

    public long TotalFrames { get; private set; }
    public float TotalSeconds { get; private set; }
    public float AverageFramesPerSecond { get; private set; }
    public float CurrentFramesPerSecond { get; private set; }

    public const int MAXIMUM_SAMPLES = 100;

    private Queue<float> _sampleBuffer = new Queue<float>();

    public override bool Update(float deltaTime)
    {
        CurrentFramesPerSecond = 1.0f / deltaTime;

        _sampleBuffer.Enqueue(CurrentFramesPerSecond);

        if (_sampleBuffer.Count > MAXIMUM_SAMPLES)
        {
            _sampleBuffer.Dequeue();
            AverageFramesPerSecond = _sampleBuffer.Average(i => i);
        } 
        else
        {
            AverageFramesPerSecond = CurrentFramesPerSecond;
        }

        TotalFrames++;
        TotalSeconds += deltaTime;
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要做的就是在主Game类中创建一个成员变量.

    private FrameCounter _frameCounter = new FrameCounter();
Run Code Online (Sandbox Code Playgroud)

并在Game的Draw方法中调用Update方法并绘制标签,但是你喜欢..

    protected override void Draw(GameTime gameTime)
    {
         var deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

         _frameCounter.Update(deltaTime);

         var fps = string.Format("FPS: {0}", _frameCounter.AverageFramesPerSecond);

         _spriteBatch.DrawString(_spriteFont, fps, new Vector2(1, 1), Color.Black);

        // other draw code here
    }
Run Code Online (Sandbox Code Playgroud)

请享用!:)


Dar*_*ius 5

您可以使用以下公式在任何给定时刻获取当前帧速率:

framerate = (1 / gameTime.ElapsedGameTime.TotalSeconds);
Run Code Online (Sandbox Code Playgroud)

下面介绍的其他两种方法都可以为您提供经过修改的帧速率,旨在使帧速率更平滑并且返回值的波动较小

这是通过以对数比例对所有先前帧时间加权来实现的。我不喜欢使用平均值来获得游戏性能指标的想法,因为不能很好地表示丢帧(或者如果您有很高的平均值,则根本不表示),并且如果帧率非常低/非常高,则帧间的准确性差异很大它们以相同的平均值运行。

为了解决这个问题,我制作了一个SmartFramerate类(这个名字很糟糕,我知道)

class SmartFramerate
{
    double currentFrametimes;
    double weight;
    int numerator;

    public double framerate
    {
        get
        {
            return (numerator / currentFrametimes);
        }
    }

    public SmartFramerate(int oldFrameWeight)
    {
        numerator = oldFrameWeight;
        weight = (double)oldFrameWeight / ((double)oldFrameWeight - 1d);
    }

    public void Update(double timeSinceLastFrame)
    {
        currentFrametimes = currentFrametimes / weight;
        currentFrametimes += timeSinceLastFrame;
    }
}
Run Code Online (Sandbox Code Playgroud)

在创建变量时设置权重:(权重越高,瞬时帧速率越准确,权重越低,平滑度越高。我发现3-5是一个很好的平衡点)

SmartFramerate smartFPS = new SmartFramerate(5);
Run Code Online (Sandbox Code Playgroud)

在将每帧运行的任何地方调用Update方法:

smartFPS.Update(gameTime.ElapsedGameTime.TotalSeconds);
Run Code Online (Sandbox Code Playgroud)

可以像这样访问当前帧速率:

smartFPS.framerate
Run Code Online (Sandbox Code Playgroud)

或像这样打印:

debuginfo.Update("\n\n?" + smartFPS.framerate.ToString("0000"), true);
Run Code Online (Sandbox Code Playgroud)

(我将其放入自定义打印类中,因此,如果语法看起来很时髦,我深表歉意)

但是,如果您只想将一定数量的帧平均在一起,那么该类是我想出的最有效的方法。

class SmoothFramerate
{
    int samples;
    int currentFrame;
    double[] frametimes;
    double currentFrametimes;

    public double framerate
    {
        get
        {
            return (samples / currentFrametimes);
        }
    }

    public SmoothFramerate(int Samples)
    {
        samples = Samples;
        currentFrame = 0;
        frametimes = new double[samples];
    }

    public void Update(double timeSinceLastFrame)
    {
        currentFrame++;
        if (currentFrame >= frametimes.Length) { currentFrame = 0; }

        currentFrametimes -= frametimes[currentFrame];
        frametimes[currentFrame] = timeSinceLastFrame;
        currentFrametimes += frametimes[currentFrame];
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用它,只需在要使用它的地方初始化一个SmoothFramerate变量,并传递要平均的帧数:

SmoothFramerate smoothFPS = new SmoothFramerate(1000);
Run Code Online (Sandbox Code Playgroud)

完全像使用上面的SmartFramerate类一样更新,访问和打印当前帧速率。

感谢您的阅读,希望对您有所帮助。