Определение XNA Game Lag - PullRequest
       17

Определение XNA Game Lag

6 голосов
/ 07 сентября 2011

Я сейчас создаю игру Tower Defense, используя C # & XNA.Некоторое время игры идут нормально и гладко, но после продолжительного времени игры (после появления достаточного количества врагов / башен / пуль) игра, кажется, замедляется в геометрической прогрессии.Даже когда все экземпляры очищены, задержка все еще сохраняется.

Сначала я подумал, что это может быть связано со сборкой мусора (и, возможно, так и есть), но для проверки я написал деструкторы для печати, когда объект был собран ивсе выглядит хорошо (все объекты собраны).Так что мне любопытно, есть ли у кого-нибудь опыт с лагом в XNA и его возможными причинами?

РЕДАКТИРОВАТЬ: Это для ПК

Ответы [ 4 ]

1 голос
/ 07 сентября 2011

Если вы беспокоитесь о том, что сборка мусора влияет на производительность, одним из лучших инструментов, которые вы можете научиться использовать, является CLR Profiler .Эта утилита позволяет вам профилировать распределения кучи, выполняемые вашей программой, чтобы вы могли определить, какие именно методы генерируют мусор.Помните, что много неочевидных вещей может выделяться в куче: объединение строк, индексирование словарей с ключами перечисления, замыкания, делегаты и т. Д. Даже небольшой мусор, генерируемый один раз за кадр со скоростью 60+ кадров в секунду, может быстро сложитьсяпри правильных обстоятельствах.

Тем не менее, то, что вы описали, для меня не похоже на проблему со сборкой мусора.Как правило, сборщик мусора достаточно быстр, даже во время полного сбора, чтобы вызвать сброс только нескольких кадров - другими словами, вы будете часто замечать незначительный раздражающий рывок, но не постоянное замедление.

(Предостережение: это применимо только к ПК, который имеет очень сложный GC по сравнению с другими платформами XNA.)

Вы должны попытаться подключить профилировщик к своему коду, чтобы определить, какие методы используютсясамый длинный для завершения;если ваша проблема не связана с GC, это может быть информативно.В прошлом я использовал EQATEC , хотя у меня были проблемы с некоторыми из их последних версий.Вы можете попробовать это, или вы можете посмотреть на Google в поисках альтернативы.

1 голос
/ 07 сентября 2011

Есть две вещи, которые я использовал для проверки производительности.

1) В App Hub есть Производительность , которую вы можете использовать, чтобы определить, что вы улучшаете.

2) Сейчас это немного устарело, но для Xbox 360 этот документ мне очень помог .

Обновление: также я забыл о этой презентации Gamefest 2010 .Это также касается нескольких вещей.

0 голосов
/ 16 сентября 2011

Вы не забыли отцепить события? В приведенном ниже примере я добавляю в список 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");
      }    
  }
0 голосов
/ 07 сентября 2011

Увеличено ли время игрового цикла? Добавьте секундомер в начало и конец цикла обновления и цикла рисования. Если оно увеличивается, попробуйте исключить (перемещайте 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 ()).

Каждый раз, когда отображаемое число уменьшается, запускается сборка мусора.

...