绘制期间的滚动滞后
Scrolling lag during draw
我已经开始使用 xna/monogame 开发一款新游戏。我以前设计过一些 2D 游戏,但决定制作这个对我来说是新的等距游戏。我一直在使用 reimers isometric tile engine 教程,大部分最简单级别的绘图代码都是这个的副本。
在地图上滚动时,屏幕出现卡顿现象,我只能将其描述为滞后。我打开了一个 FPS 计数器,它一直稳定在 60,所以我认为这是某种图形问题。
我曾尝试注释掉绘图代码的各个部分以缩小问题范围,但似乎没有取得任何进展,但这几周前并没有发生,所以我相信它是我添加的东西,也许导致它的 tilesets 有问题吗?
如有任何建议,我们将不胜感激。我没有在这里放任何代码,因为它变成了一个相当大的项目,我不知道应该关注哪个领域,但我已经上传了整个项目 here 如果有人愿意调查的话。
Tl;dr 您正在创建一个名为 dummyTexture
的新 Texture2D
实例(1x1 像素)每次调用 DrawMiniMap
方法.这是个坏主意,因为每次都需要将纹理发送到 GPU(然后处理和收集)。添加一个名为 dummyTexture
的字段并在 LoadContent
.
中完全初始化它
但请阅读 post 的其余部分,了解如何识别这些问题。
您的 Update
方法正在以 60fps 的速度被调用,但是对于 Draw
方法也不一定如此。由于 Game.IsFixedTimeStep
默认设置为 true
,一旦 Monogame 发现 Draw
花费的时间比预期的要长,您的 Draw
方法将跳过帧。
由于您现在编写游戏逻辑的方式,这是 Monogame 确保所有更新都在固定时间步长内完成的唯一方法。
为了更好地了解正在发生的事情,首先为 Draw
方法 fps 创建一组额外的 fps 变量,并将这两个值呈现在屏幕上。您会看到 Update
以 60 fps 绘制,但 Draw
低于该值。
protected override void Draw(GameTime gameTime)
{
// similar to what you have inside `Update`
drawFpsTimer += gameTime.ElapsedGameTime;
drawFpsCount++;
if (drawFpsTimer >= TimeSpan.FromSeconds(1))
{ drawFpsTimer = TimeSpan.FromSeconds(0); drawFps = drawFpsCount; drawFpsCount = 0; }
...
有了这个,就可以很容易地查明 Draw
中有问题的方法,并让你的 fps 回到 60。
此外,通过将 IsFixedTimeStep
设置为 false
,您可以连续调用 Update
和 Draw
,但是您的 Update
帧速率也会下降 - 这意味着您应该更改所有更新逻辑以使用 gameTime.ElapsedGameTime
而不是假定固定步骤:
protected override void Initialize()
{
// use variable time step
this.IsFixedTimeStep = false;
this.TargetElapsedTime = TimeSpan.FromSeconds(1 / 60.0);
this.graphics.SynchronizeWithVerticalRetrace = true;
...
我更喜欢在我的所有项目中使用可变时间步长,尤其是当您发现 XNA sometimes takes up 100% CPU time on one core when the default value of Game.IsFixedTimeStep
is used 时,但请准备好进行一些重构。
至于为什么跳帧,好像是DrawMiniMap
方法有问题。将此注释掉可在我的机器上提供 60 fps 更新 + 60 fps 绘制速率。
经进一步检查,发现您在 每次调用此方法 时创建一个名为 dummyTexture
的新 Texture2D
实例(1x1 像素)。这是一个坏主意。添加一个名为 dummyTexture
的字段并在 LoadContent
中完全初始化它。您还可以通过使 tileColour
成为 Tile
class 的成员来稍微加快此方法的速度,以避免在每次迭代时进行一堆 if
测试,但可能有很多优化像这样,除非您部署到移动设备,否则可能不需要。
我已经开始使用 xna/monogame 开发一款新游戏。我以前设计过一些 2D 游戏,但决定制作这个对我来说是新的等距游戏。我一直在使用 reimers isometric tile engine 教程,大部分最简单级别的绘图代码都是这个的副本。
在地图上滚动时,屏幕出现卡顿现象,我只能将其描述为滞后。我打开了一个 FPS 计数器,它一直稳定在 60,所以我认为这是某种图形问题。
我曾尝试注释掉绘图代码的各个部分以缩小问题范围,但似乎没有取得任何进展,但这几周前并没有发生,所以我相信它是我添加的东西,也许导致它的 tilesets 有问题吗?
如有任何建议,我们将不胜感激。我没有在这里放任何代码,因为它变成了一个相当大的项目,我不知道应该关注哪个领域,但我已经上传了整个项目 here 如果有人愿意调查的话。
Tl;dr 您正在创建一个名为 dummyTexture
的新 Texture2D
实例(1x1 像素)每次调用 DrawMiniMap
方法.这是个坏主意,因为每次都需要将纹理发送到 GPU(然后处理和收集)。添加一个名为 dummyTexture
的字段并在 LoadContent
.
但请阅读 post 的其余部分,了解如何识别这些问题。
您的 Update
方法正在以 60fps 的速度被调用,但是对于 Draw
方法也不一定如此。由于 Game.IsFixedTimeStep
默认设置为 true
,一旦 Monogame 发现 Draw
花费的时间比预期的要长,您的 Draw
方法将跳过帧。
由于您现在编写游戏逻辑的方式,这是 Monogame 确保所有更新都在固定时间步长内完成的唯一方法。
为了更好地了解正在发生的事情,首先为 Draw
方法 fps 创建一组额外的 fps 变量,并将这两个值呈现在屏幕上。您会看到 Update
以 60 fps 绘制,但 Draw
低于该值。
protected override void Draw(GameTime gameTime)
{
// similar to what you have inside `Update`
drawFpsTimer += gameTime.ElapsedGameTime;
drawFpsCount++;
if (drawFpsTimer >= TimeSpan.FromSeconds(1))
{ drawFpsTimer = TimeSpan.FromSeconds(0); drawFps = drawFpsCount; drawFpsCount = 0; }
...
有了这个,就可以很容易地查明 Draw
中有问题的方法,并让你的 fps 回到 60。
此外,通过将 IsFixedTimeStep
设置为 false
,您可以连续调用 Update
和 Draw
,但是您的 Update
帧速率也会下降 - 这意味着您应该更改所有更新逻辑以使用 gameTime.ElapsedGameTime
而不是假定固定步骤:
protected override void Initialize()
{
// use variable time step
this.IsFixedTimeStep = false;
this.TargetElapsedTime = TimeSpan.FromSeconds(1 / 60.0);
this.graphics.SynchronizeWithVerticalRetrace = true;
...
我更喜欢在我的所有项目中使用可变时间步长,尤其是当您发现 XNA sometimes takes up 100% CPU time on one core when the default value of Game.IsFixedTimeStep
is used 时,但请准备好进行一些重构。
至于为什么跳帧,好像是DrawMiniMap
方法有问题。将此注释掉可在我的机器上提供 60 fps 更新 + 60 fps 绘制速率。
经进一步检查,发现您在 每次调用此方法 时创建一个名为 dummyTexture
的新 Texture2D
实例(1x1 像素)。这是一个坏主意。添加一个名为 dummyTexture
的字段并在 LoadContent
中完全初始化它。您还可以通过使 tileColour
成为 Tile
class 的成员来稍微加快此方法的速度,以避免在每次迭代时进行一堆 if
测试,但可能有很多优化像这样,除非您部署到移动设备,否则可能不需要。