动画帧率 vs 游戏 fps

Animation frame rate vs game fps

我是刚开始使用 MonoGame 的初级程序员。我正在为 运行 动画实现一些代码,遇到了一个我不知道如何解决的问题。这是我在 AnimationManager class:

中使用的代码
public void Update(GameTime gameTime)
{
    timeElapsed += (float)gameTime.ElapsedGameTime.TotalSeconds;

    if (timeElapsed > timeToUpdate)
    {
        timeElapsed -= timeToUpdate;
        //Tried to just reset timeElapsed to zero, still doesn't work
        //timeElapsed = 0;
        if (frameIndex < rectangles.Count -1)
        {
            frameIndex++;
        }
        else if (isLooping)
        {
            frameIndex = 0;
        }
    }
}

问题是我以每秒 24 帧的速度制作动画,当游戏以 60 或 30 帧/秒的速度运行时,每次更新代码检查是时候绘制新的动画帧时,您会得到一些剩余的帧,因为你试图每秒平均绘制 24 张图像,每秒平均绘制 30 个游戏帧。所以还有剩下的 6 帧。这样做的结果是大约 6 帧动画被绘制了两次,有些被跳过了,整个动画长了大约 25%。有没有办法来解决这个问题?我是否可以将此代码移动到 Draw call,然后将 60 fps 游戏的 draw calls 限制在 48 fps,这样每个动画帧将在每隔一个 draw call 绘制。如果这是一个合理的解决方案,我不知道该怎么做?

VSync 最终将如何影响这一切。即使解决了这个问题,它会不会弄乱动画帧。

编辑:忘了说这是一款 2d 游戏,手绘动画。

通常,当您进行此类操作时,无需担心 VSync 或您的游戏 运行s 为 60 或 30 fps 的事实。这几乎是无关紧要的。

重要的是您知道动画的每秒所需帧数以及单个游戏帧需要多长时间。

由此您可以计算出 单个动画帧 的时间长度。例如,您最终会得到这样的结果:

var animationFrameTime = 1f / 24f;   // 24 frames per second

到目前为止一切顺利。

接下来你需要做的是开始在某个地方积累时间。有几种不同的方式来考虑这个问题。我喜欢根据到下一帧还剩多少时间来考虑

var gameFrameTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
timeUntilNextFrame -= gameFrameTime;

那么当你 运行 超出帧时间时,你需要增加 frameIndex

if(timeUntilNextFrame <= 0)
{
    frameIndex++;
    timeUntilNextFrame += animationFrameTime;
}

注意这里的重要一点。我已经 添加 animationFrameTimetimeUntilNextFrame。这样,如果前一帧有任何剩余时间,它将被添加到下一帧,保持动画流畅。

真的没有比这更多的了。我省略了 rectangles.CountisLooping 位,但将它们重新添加应该很容易。您可能还想将 timeUntilNextFrame 初始化为 animationFrameTime第一帧。

只是对这段代码发出警告,如果游戏由于某种原因 运行 运行缓慢(或者可能暂停),gameFrameTime 最终可能会有一个非常大的值,导致一些奇怪的行为。我不完全确定这是否会在 MonoGame / XNA 中发生,但至少值得考虑。

原来这是一个众所周知的问题。基本上,在 30 个游戏 fps 中阻塞 24 个动画 fps 在数学上是不可能的,因为它们不是彼此独立的。插值是解决此问题的唯一方法。这与在 60 赫兹显示器上观看 24 fps 电影时所做的相同。

https://en.wikipedia.org/wiki/Three-two_pull_down