确定XNA游戏延迟

时间:2011-09-07 15:31:22

标签: c# garbage-collection xna

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

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

编辑:这是针对PC的

4 个答案:

答案 0 :(得分:1)

我曾经用两件事来检查表现。

1)App Hub有一个Performance utility,您可以用它来帮助确定您的改进。

2)现在有点老了,但是for the Xbox 360 this document helped me a lot

更新:我也忘记了this Gamefest 2010 presentation。它也涉及一些事情。

答案 1 :(得分:1)

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

那就是说,你所描述的对我来说听起来不像垃圾收集的问题。即使在完整收集过程中,GC通常也足够快,只会导致丢帧数 - 换句话说,你会经常注意到一个轻微的,恼人的混蛋,但不会持续减速。

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

您应该尝试将探查器附加到您的代码中,以确定哪些方法花费的时间最长;如果您的问题与GC无关,这可能会提供信息。在过去,我使用了EQATEC,虽然我的一些较新版本存在问题。你可以尝试那个,或者你可以在谷歌上寻找替代方案。

答案 2 :(得分:0)

游戏循环时间是否增加?将秒表添加到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())。

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

答案 3 :(得分:0)

你不会忘记揭开事件是你吗?在下面的示例中,我将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");
      }    
  }