确定 XNA 游戏延迟

发布于 2024-12-03 07:18:43 字数 231 浏览 1 评论 0 原文

我目前正在使用 C# 和 C# 创建塔防游戏。 XNA。游戏运行良好且流畅一段时间,但玩了很长一段时间后(在产生足够的敌人/塔/子弹后),游戏似乎呈指数级减慢。即使清除所有实例,延迟仍然存在。

起初我认为这可能与垃圾收集有关(也许确实如此),但为了测试它,我编写了析构函数来打印何时收集了对象并且一切看起来都很好(所有对象都被收集了)。所以我很好奇是否有人有 XNA 滞后的经验以及可能的原因?

编辑:这是针对PC的

I'm currently creating a tower defense game using C# & XNA. The games runs fine and smoothly for a while but after playing for a good amount of time (after sufficient enemies/towers/bullets have spawned) the game seems to slow exponentially. Even when all instances are cleared the lag still persists.

At first I thought this might have to do with garbage collection (and perhaps it does) but to test it I wrote destructors to print when an object was collected and everything looks fine (all objects are collected). So I'm curious if anyone has any experience with lag in XNA and the possible causes of it?

EDIT: This is for PC

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

自此以后,行同陌路 2024-12-10 07:18:43

我用两件事来检查性能。

1) App Hub 有一个性能实用程序,您可以使用它来帮助确定您需要改进的地方。

2) 这现在有点旧了,但是对于 Xbox 360,此文档帮助了我很多

更新:我还忘记了这个 Gamefest 2010 演示。它还讨论了一些事情。

There's two things that I've used to check out performance.

1) App Hub has a Performance utility that you can use to help determine what youc an improve.

2) This is a bit old now, but for the Xbox 360 this document helped me a lot.

Update: also I forgot about this Gamefest 2010 presentation. It also goes over a few things.

愿与i 2024-12-10 07:18:43

如果您担心垃圾收集会影响性能,您可以学习使用的最佳工具之一是 CLR 探查器。该实用程序允许您分析程序执行的堆分配,以便您可以确定哪些方法正在生成垃圾。请记住,许多不明显的事情可以分配到堆上:连接字符串、使用枚举键索引字典、闭包、委托等。即使是一点垃圾,以每秒 60 帧以上的速度每帧生成一次,也可以快速累加在适当的情况下。

也就是说,您所描述的对我来说听起来不像是垃圾收集的问题。 GC 通常足够快,即使在完整的收集过程中,也只会导致丢失几帧 - 换句话说,您会时不时地注意到一个轻微的、烦人的抖动,但不会持续缓慢。

(警告:这仅适用于 PC,与其他 XNA 平台相比,PC 具有非常复杂的 GC。)

您应该尝试将分析器附加到代码中,以识别哪些方法需要最长的时间才能完成;如果您的问题与 GC 无关,这可能会提供一些信息。过去,我曾使用过 EQATEC,尽管我在使用某些功能时遇到了问题他们的最新版本。你可以尝试一下,或者你可以在谷歌上寻找替代方案。

If you're worried that garbage collections are impacting performance, one of the best tools you can learn to use is the CLR Profiler. This utility allows you to profile the heap allocations performed by your program, so that you can identify which exactly methods are generating garbage. Remember that a lot of non-obvious things can allocate onto the heap: concatenating strings, indexing dictionaries with enumeration keys, closures, delegates, etc. Even a little garbage, generated once per frame at 60+ frames per second, can quickly add up under the right circumstances.

That said, what you've described doesn't sound like a problem with garbage collection to me. The GC is generally quick enough, even during a complete collection, to only cause a few frames to be dropped -- in other words, you'll notice a minor, annoying jerk every so often, but not a persistent slowdown.

(Caveat: this only applies on the PC, which has a very sophisticated GC compared to other XNA platforms.)

You should try attaching a profiler to your code to identify which methods are taking the longest to complete; if your problem isn't related to GC, this may be informative. In the past, I've used EQATEC, although I've had issues with some of their more recent versions. You can try that one, or you can look around on Google for an alternative.

小鸟爱天空丶 2024-12-10 07:18:43

游戏循环时间是否增加?将秒表添加到 Update 循环和 Draw 循环的开头和结尾。如果它正在增加,请尝试排除(移动 stopwatch.Start() 和/或 stopwatch.Stop() ),直到找到导致速度减慢的原因。如果没有增加,则可能是由其他原因引起的。

尝试将此行添加到代码中:(

SpriteBatch.DrawInt64(Font, GC.GetTotalMemory(false) / 1000 /* in kilobytes */,
POSITION, Color.White, 0f);

DrawInt64/32 是 spritebatch 的非常有用的扩展,它允许您绘制数字而不生成垃圾,可在此处获取: http://pastebin.com/pVw66mGy 。或者只使用 DrawString 和 .ToString() )。

每当显示的数字减少时,就会运行垃圾收集。

Is the game loop time increased ? Add stopwatch's to the start and to the end of the Update loop and the Draw loop. If it is increasing, try to rule out ( move stopwatch.Start() and/or stopwatch.Stop() ) until you find which causes the slow down. If it is not increasing, it's caused by something else.

Try to add this line to the code:

SpriteBatch.DrawInt64(Font, GC.GetTotalMemory(false) / 1000 /* in kilobytes */,
POSITION, Color.White, 0f);

( DrawInt64/32 is really useful extension to spritebatch which allows you to draw numbers without generating garbage, available here: http://pastebin.com/pVw66mGy . Alternatively just use DrawString and .ToString() ).

Everytime the number displayed decreases, garbage collection is ran.

浮生面具三千个 2024-12-10 07:18:43

你不会忘记取消事件吧?在下面的示例中,我将 4 个精灵添加到列表中,每个精灵都挂钩游戏中的一个事件。然后我删除一个精灵并引发该事件。

在这种情况下,所有 4 个精灵仍然处于活动状态并引发其事件,因为游戏中仍然存在对它们的引用。

只是一个想法,如果您为游戏对象使用事件,则可能会让它们全部运行静止。

class Game
{
  public event EventHandler SomeEvent;
  List<Sprite> sprites;

  public Game()
  {
    sprites = new List<Sprite>();
    sprites.Add(new Sprite(this));
    sprites.Add(new Sprite(this));
    sprites.Add(new Sprite(this));
    sprites.Add(new Sprite(this));

    sprites.RemoveAt(0);

    EventHandler temp = SomeEvent;
    if (temp != null)
    {
        temp(this, EventArgs.Empty);
    }
  }

  static void Main(string[] args)
  {
      Game newProgram = new Game();
  }



  class Sprite
  {
      public Sprite(Game gameReference)
      {
          gameReference.SomeEvent += new EventHandler(gameReference_SomeEvent);
      }

      void gameReference_SomeEvent(object sender, EventArgs e)
      {
          Debug.WriteLine("Event");
      }    
  }

You're not forgetting to unhook events are you? in the example below I add 4 sprites to a list, each sprite hooks an event from the game. I then remove a sprite and raise the event.

In this situation all 4 sprites are still active and get their event raised because there is still a reference to them in Game.

just a thought, if you're using events for your game objects you could be leaving them all running still.

class Game
{
  public event EventHandler SomeEvent;
  List<Sprite> sprites;

  public Game()
  {
    sprites = new List<Sprite>();
    sprites.Add(new Sprite(this));
    sprites.Add(new Sprite(this));
    sprites.Add(new Sprite(this));
    sprites.Add(new Sprite(this));

    sprites.RemoveAt(0);

    EventHandler temp = SomeEvent;
    if (temp != null)
    {
        temp(this, EventArgs.Empty);
    }
  }

  static void Main(string[] args)
  {
      Game newProgram = new Game();
  }



  class Sprite
  {
      public Sprite(Game gameReference)
      {
          gameReference.SomeEvent += new EventHandler(gameReference_SomeEvent);
      }

      void gameReference_SomeEvent(object sender, EventArgs e)
      {
          Debug.WriteLine("Event");
      }    
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文