15

我做了一个 XNA 图像查看器,但它总是重绘场景,即使它没有改变,而且它让我的上网本像地狱一样燃烧,所以我希望它在没有任何变化时暂停绘图。

将帧速率降低到 1 是让它保持凉爽的一种方法,但它会导致输出滞后。

没有输入时如何防止重绘?


这个问题解决了,但又发现了另一个问题——当它的窗口处于焦点时,游戏会消耗大量的 CPU,而当它没有焦点时,它只占用大约 1% 的 CPU。有关如何解决此其他问题的详细信息,请参阅此问题:

如何在没有任何值得计算的事情发生的情况下减少 XNA 游戏 CPU 使用率?

4

2 回答 2

11

为此,您可以使用Game.SupressDraw方法。从链接的评论中:

在 Update 期间调用此方法可防止在下次调用 Update 之前对 Draw 进行任何调用。如果显示没有因更新而改变,则此方法可用于小型设备以延长电池寿命。例如,如果屏幕是静态的,没有背景动画,则可以在更新期间检查玩家输入以确定玩家是否正在执行任何操作。如果未检测到输入,则此方法允许游戏跳过绘图直到下一次更新。

例如,以下代码只会调用该Draw函数一次。当我对此进行测试时,我注意到在没有SuppressDraw调用的情况下 CPU 使用率很高(70%)。使用SupressDraw时,CPU 使用率急剧下降(低于 15%)。您的数字可能会有所不同。

public class Game1 : Microsoft.Xna.Framework.Game
{
    ...
    private bool _drawn = false;
    protected override void Update(GameTime gameTime)
    {
        if (_drawn)
            SuppressDraw();
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        /* draw stuff here */
        spriteBatch.End();

        _drawn = true;
    }
    ...
}

请注意,SupressDraw仅抑制一个Draw呼叫。为了防止更多的来电,Draw你必须不断地来电SupressDrawUpdate希望这是有道理的。

于 2013-05-19T03:41:47.527 回答
0

正如公认的答案所说,您可以使用 SuppressDraw 来避免绘制未更改的框架。不管怎样,你的更新方法都会运行,这就是为什么它仍然使用比你预期更多的 CPU。为了避免使用尽可能多的 CPU,您需要以某种方式避免更新您知道自上一帧以来没有更改的内容。

我假设您会像知道何时禁止绘制一样知道这一点,因此您需要做的是重新排列更新方法,如下所示:

private void Update(GameTime gameTime)
{
    var frameHasChanges = DetectChanges(); //This method you need to figure out yourself
    if (!frameHasChanges)
    {
        SuppressDraw();
        base.Update(gameTime);
        return;
    }

    //Do the rest of normal Update

}

最后一点;我从来没有在我做过的任何游戏中使用它。我觉得这表明您可能还有其他一些潜在的性能问题。但是,我使用了许多技术来避免在每一帧上渲染文本等(导致装箱/拆箱)。如果您想了解更多信息,请在评论中询问。

于 2013-05-23T12:59:32.153 回答