我做了一个 XNA 图像查看器,但它总是重绘场景,即使它没有改变,而且它让我的上网本像地狱一样燃烧,所以我希望它在没有任何变化时暂停绘图。
将帧速率降低到 1 是让它保持凉爽的一种方法,但它会导致输出滞后。
没有输入时如何防止重绘?
这个问题解决了,但又发现了另一个问题——当它的窗口处于焦点时,游戏会消耗大量的 CPU,而当它没有焦点时,它只占用大约 1% 的 CPU。有关如何解决此其他问题的详细信息,请参阅此问题:
我做了一个 XNA 图像查看器,但它总是重绘场景,即使它没有改变,而且它让我的上网本像地狱一样燃烧,所以我希望它在没有任何变化时暂停绘图。
将帧速率降低到 1 是让它保持凉爽的一种方法,但它会导致输出滞后。
没有输入时如何防止重绘?
这个问题解决了,但又发现了另一个问题——当它的窗口处于焦点时,游戏会消耗大量的 CPU,而当它没有焦点时,它只占用大约 1% 的 CPU。有关如何解决此其他问题的详细信息,请参阅此问题:
为此,您可以使用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
你必须不断地来电SupressDraw
。Update
希望这是有道理的。
正如公认的答案所说,您可以使用 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
}
最后一点;我从来没有在我做过的任何游戏中使用它。我觉得这表明您可能还有其他一些潜在的性能问题。但是,我使用了许多技术来避免在每一帧上渲染文本等(导致装箱/拆箱)。如果您想了解更多信息,请在评论中询问。