确定XNA游戏延迟

本文关键字:延迟 游戏 XNA 确定 | 更新日期: 2023-09-27 18:08:06

我正在用c#制作一款塔防游戏;XNA。游戏在一段时间内运行得很顺利,但在玩了一段时间后(游戏邦注:在出现了足够多的敌人/塔/子弹之后),游戏速度似乎呈指数级放缓。即使清除了所有实例,延迟仍然存在。

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

编辑:这是PC

确定XNA游戏延迟

我用了两种方法来检查性能。

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

2)这是有点旧了,但对于Xbox 360这个文件帮助了我很多。

更新:我也忘记了这个Gamefest 2010的演讲。

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

也就是说,你所描述的对我来说不像是垃圾收集的问题。GC通常足够快,即使在一个完整的收集过程中,也只会导致几个帧被丢弃——换句话说,您会经常注意到一个小的、令人讨厌的停顿,但不会出现持续的减速。

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

你应该尝试在你的代码中附加一个分析器,以确定哪些方法需要最长的时间来完成;如果您的问题与GC无关,那么这可能是有用的。过去,我使用过EQATEC,尽管我在使用它们的一些最新版本时遇到了问题。你可以试试这个,或者你可以在谷歌上找一个替代的

游戏循环时间是否增加?在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())。

每次显示的数量减少,就运行垃圾收集

你不会忘记解开事件吧?在下面的例子中,我在列表中添加了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");
      }    
  }