AS3 большое снижение производительности игры с течением времени - PullRequest
9 голосов
/ 22 сентября 2009

В настоящее время я работаю над очень большой игрой на платформе Flash (сотни классов) и занимаюсь проблемой, когда игра медленно останавливается, если вы оставляете ее включенной достаточно долго. Я не писал игру, и поэтому я лишь смутно знаком с ее внутренностями. Некоторые из загадочных симптомов включают,

  • Игра будет работать нормально в течение определенного промежутка времени (на заданном уровне), когда внезапно она начнет экспоненциально вытекать из памяти.
  • Время, необходимое для того, чтобы игра достигла точки экспоненциальной утечки, короче, когда на экране появляется больше спрайтов.
  • Даже когда на экране ничего не отображается, игра замедляется.
  • Игра замедляется быстрее с более частыми столкновениями спрайтов.
  • Полное отключение кода столкновения замедляет процесс деградации, но не мешает игре пропускать кадры.

Глядя на источник и используя Flex profiler, я подозреваю, что

  • Существует множество слоняющихся объектов, особенно WeakMethodClosure, занимающих большие объемы памяти.
  • Программа чрезвычайно широко использует слабых слушателей событий (десятки отправляются за кадр).
  • BitmapData копируется каждый раз, когда создается новый спрайт. Это спрайты размером 50x50 пикселей, которые появляются со скоростью около 8 спрайтов в секунду.

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

Ответы [ 7 ]

7 голосов
/ 22 сентября 2009

Я недавно завершил оптимизацию большого проекта. И я могу дать вам несколько архитектурных советов:

  1. Основной принцип - старайтесь делать как можно меньше вызовов функций / событий
  2. Избавься от всего, кроме одного Циклы onEnterFrame / onInterval / onTimer. Делай все, что ты нужно в один вызов общего события. Вам, вероятно, понадобится много статических массивов для хранения обработанного объекта. ссылки.
  3. Делайте графику / рендеринг также в одном основном цикле
  4. Попробуйте использовать большие (возможно, предварительно обработанные) холсты вместо маленьких спрайтов / растровых изображений. Обычно его можно использовать для фона. Но также работает хорошо для небольших объектов (например, деревья, платформы и т. д.)
  5. Избавьтесь от небольших растровых ресурсов, соберите их на один лист плиток и нарисуйте свои вещи. непосредственно из него через свойство source – rect

Я надеюсь, это поможет вам! Утечки памяти - такая головная боль.

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

3 голосов
/ 22 сентября 2009
  • Избегайте анонимных методов - измените их на методы уровня класса.
  • Используйте слабую ссылку в addEventListener и / или убедитесь, что вы удалили все прослушиватели объекта перед удалением его с помощью removeChild
  • Убедитесь, что вы удалили все спрайты вместо того, чтобы просто позволить им улететь с экрана. Также, если возможно, используйте спрайты вместо создания новых.
1 голос
/ 22 сентября 2009

Вы должны рассмотреть возможность объединения объектов, если у вас много процесса создания / уничтожения, особенно с такими тяжелыми объектами, как растровые данные.

см. Класс пула объектов

0 голосов
/ 22 сентября 2009
Flash имеет довольно печально известную проблему (многие считают это ошибкой), которая приводит к тому, что слушатели событий для таймеров и события ENTER_FRAME не собирают мусор, даже если на них слабо ссылаются. Таким образом, даже несмотря на то, что рекомендуется использовать события со слабыми ссылками, вы все равно должны удалить все прослушиватели событий, когда они больше не нужны.
0 голосов
/ 22 сентября 2009

Звучит с большей вероятностью, что вы ограничиваетесь в скорости процессора, а не в памяти. Вы должны очень стараться, чтобы память закрыла приложение Flash.

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

1) Строго управляйте прослушивателями событий для всего , особенно слушателей мыши. У вас есть слушатели событий $ texas на всех ваших объектах спрайта? Это может быть проблемой.

2) Доступ к массивам с использованием int или uint вместо Number. Это огромно, и это один из тех задоров Adobe. Доступ к объекту массива с помощью int и uint намного быстрее, чем Number, и если вы выполняете много итераций (и это звучит так, как вы), это может сэкономить драгоценные миллисекунды при выполнении кадра.

3) В том же духе, что и # 2, следите за своими математическими операциями и типами, которые вы используете для определенных операций. Самая медленная вещь, которую вы можете сделать в математических операциях для AS3, - это повторное приведение (передача целых чисел в функцию, которая возвращает число) или выполнение базовых операций, таких как сложение и вычитание числа вместо числа.

Самое замечательное наличие такой программы wtfhuge во Flash - это то, что даже незначительные изменения в оптимизации могут серьезно повлиять на производительность. Однажды я играл с движком raytrace в AS3, где я объявил одну дополнительную переменную, и это убило мой FPS с 30 до 23.

0 голосов
/ 22 сентября 2009

Сначала определите, какой лимит памяти или процессора вы используете. Похоже, что позже, кажется, что много объектов делают что-то вокруг ... вероятно, эти дополнительные спрайты не освобождаются хорошо. Ищите зависимости между объектами / переменными / чем-либо в этих событиях, убедитесь, что спрайты удалены, обратите внимание на любые обработчики EnterFrame или повторяющихся событий.

0 голосов
/ 22 сентября 2009

Похоже, вам нужно профилировать приложение, чтобы увидеть, что происходит.

В этой теме было несколько предложений, но, в конечном счете, вам нужно будет просто ввести код, чтобы определить, что происходит.

Профилирование кода ActionScript-3

Возможно, вы захотите посмотреть, сможете ли вы просто запустить некоторые меньшие детали в течение определенного периода времени, и посмотрите, видите ли вы замедление.

Возможно, вы захотите выполнить модульное тестирование своего приложения, чтобы вы могли быстро запускать различные части в поисках утечек памяти. Одна структура: http://asunit.org/,, а другая: http://opensource.adobe.com/wiki/display/flexunit/

Юнит-тестирование - это то, что я очень много использую для профилирования, так что вы можете тестировать на верхнем уровне вашей игры, запускать ее тысячи раз, искать проблемы, затем запускать каждую часть и видеть, в чем есть проблемы, и просто работать твой путь вниз. Это ручной процесс, но если две идеи в SO-потоке, перечисленные в начале, не помогают, это может быть вашим лучшим подходом.

Вы используете слишком много памяти? Или ваш процессор слишком высок?

...