Одна из основных проблем, с которыми сталкиваются разработчики игр – низкая производительность их творения. NET XNA не является исключением в этом вопросе, а скорее даже наоборот, т.к. за легкость разработки игры приходится жертвовать производительностью.

Если вы хотите получить в итоге хорошую игру, а не очередную поделку на коленях, то вам придется начать задумываться об оптимизации производительности XNA. В этой статье я поделюсь некоторыми не очевидными моментами, касающиеся разработки игр на NET XNA, которые мне удалось узнать. Если у вас есть что добавить – прошу вас сделать это в комментариях.

  • Использование массивов вместо List<> достаточно сильно ускоряет работу приложения. Особенно при наличии в игре огромных массивов.
  • Следует избегать использование оператора цикла foreach. В этом случае использование for приводит к увеличению производительности NET:

  • При выводе на экран графики, используйте атласы текстур. Атлас текстур – это набор из нескольких текстур, помещенных на одну текстуру. Это значительно ускоряет вывод графики на экран, особенно в 2D приложениях
  • При выводе 2D графики с использованием SpriteBatch старайтесь минимизировать количество SpriteBatch.Begin() и SpriteBatch.End(). Бывают такие ситуации, когда вам необходимо наличие нескольких открытий и закрытий SpriteBatch в цикле рисования, но вы должны постараться минимизировать их количество, если хотите достичь максимальной производительности вашего GPU. В идеале должен быть только один SpriteBatch
  • Используйте многопоточность вашего процессора. Если ваш профпайлер показывает, что NET XNA упираетесь в производительность вашего CPU, то использование многопотоности увеличит производительность XNA. Очень часто обработку частиц, системы столкновений выносят во второй поток приложения, но теоретически, при достаточном количестве работы, вы можете вынести практически любую подсистему в другой поток.
  • Ручная подстановка часто используемого кода. В определенный момент вы столкнетесь с тем, что сделано уже все возможное, чтобы увеличить производительность NET XNA, но ее все равно не достаточно. В этом случае вам поможет ручная подстановка кода часто используемых методов. Это не что иное, как избавление от обработки лишних вызовов функций:
  • сменится на

    Определить часто вызываемые функции вам сможет профайлер.

  • Как следует из прошлого пункта, следует убрать из кода приложения вызовы всех пустых функций, и особенно пустые деструкторы.
  • При наличии проверок на выполнение метода такого вида:
  • Оптимальнее будет проверять условие выхода из метода класса myObject до вызова метода Update(), т.к. вызов метода в C# занимает достаточно большое время и, при большом количестве объектов, задержка, возникающая в следствии пустых вызовов, может достигать значительного времени.

  • Кешируйте данные везде, где только возможно. Например, как часто при отрисовке текстуры вы делаете так:
  • Каждый кадр вы создаете новый объект Rectangle, который не меняется в методе Draw. В этом случае можно оптимизировать код, вынеся код создания прямоугольника за пределы Draw:

  • Индексирование массивов. Вы можете увеличить производительность NET, если будете кешировать обращение к элементам массивов. Обращение к элементу массива занимает столько же времени, как и вызов функции + еще немного на проверку вхождения в границы массива. Вы можете ускорить выполнение своей программы изменим:
  • на

  • Векторные операции. Net XNA предоставляет нам возможности широкого использования векторов, производительность вычисления которых намного выше стандартных функций языка C#. При каждой возможности старайтесь использовать инструментарий Vector2. Например: