Flash AS3 - removeChild () используется для полного удаления объекта? - PullRequest
1 голос
/ 09 февраля 2011

Я создаю игру с астероидами, и у меня в основном классе возникают проблемы с пулями, выпущенными кораблем.

Все пули относятся к классу "Пули" и хранятся вмассив под названием «пули» в основном классе.Когда маркеры выходят из экрана, вызывается метод removeBullet (bulletID) в основном классе.

private function removeBullet(id:int)
    {
        removeChild(bullets[id]);
        bullets.splice(id);
    }

В моем классе Bullet у меня есть прослушиватель enterFrame, который отслеживает «stillHere».Поэтому, как только пуля добавляется на главную сцену с помощью addChild, в моей панели вывода появляется всплывающее окно «stillHere».

Моя проблема в том, что даже после того, как я вызываю removeBullet, «stillHere» продолжает появлятьсяпанель вывода, которая сообщает мне, что объект, который я пытался удалить, все еще остается где-то в памяти.

Что я могу сделать, чтобы полностью избавиться от него?

Ответы [ 2 ]

4 голосов
/ 09 февраля 2011

Поскольку вы находитесь в ActionScript, у вас нет прямого контроля над удалением объектов.

Настоящая проблема, с которой вы столкнулись, заключается в том, что ваши слушатели событий все еще стреляют. Очевидно, вы можете решить эту проблему, позвонив removeEventListener, когда они будут удалены.

Однако лучший подход - это иметь только одного ENTER_FRAME слушателя на всю игру. Для этого нужно будет индивидуально продвигать все элементы игры (корабль, астероиды, пули, обломки и т. Д.). Этот метод удаляет все шансы того, что вы случайно забыли удалить прослушиватели событий, а также делает код более понятным, поскольку вы можете видеть порядок обновления элементов за определенный временной шаг.

У меня обычно есть временная функция destroy, которая читает что-то вроде этого:

public function destroy():void {
    stop(); // if it's a MovieClip
    if(parent) parent.removeChild(this);
}

Пока я вызываю эту функцию, а затем удаляю ссылки на объект, она обычно собирается.

По этой причине в моем коде очень редко есть слушатели отдельных объектов.

4 голосов
/ 09 февраля 2011

Слушатель событий вполне может быть причиной того, что он все еще находится в памяти. Это не хороший способ проверить, было ли что-то собрано или нет.

Кроме того, даже если бы это был хороший способ проверить, был ли объект собран мусором, сбор не является мгновенным процессом. Flash Player запускает gc только тогда, когда ему нужно выделить больше памяти и он не может этого сделать.

При условии, что у вас нет других ссылок на объект маркера, кроме списка отображения и массива маркеров, то того, что вы сделали, достаточно, чтобы он стал сборщиком мусора.

РЕДАКТИРОВАТЬ: Чтобы ответить на вопрос о том, есть ли способ наблюдать, был ли объект был собран ...

Вы можете использовать объект как ключ в словаре со слабым ключом.

private var _dict:Dictionary = new Dictionary(true);
_dict[bullet] = "Bullet is still here...";

Тогда всякий раз, когда вы хотите проверить, существует ли пуля, вы используете цикл for ... in для итерации ключей

for(var key:* in _dict){
    trace(key + " " + _dict[key]);
}

Поскольку ключи со слабым ключом словаря не считаются ссылками для целей сборки мусора, это работает.

Если вы очень обеспокоены утечками памяти, вы можете записать пул объектов, в который вы помещаете старые объекты маркеров, которые вы удаляете со сцены, и просто использовать их снова и снова. Таким образом, вы никогда не допустите, чтобы любые пули собирались мусором, но вы, вероятно, когда-либо создадите только небольшое, ограниченное количество пуль (то есть количество пуль, которые пользователь когда-либо видит на экране одновременно при данное время). Это может быть лучшим решением для вас, поскольку пули, вероятно, занимают мало места в памяти, и вы получаете бонус, не заставляя Flash очищать свой мусор. Запуск GC приводит к снижению производительности во время удаления мусора, поэтому с помощью этой меры делать все возможное, чтобы предотвратить даже необходимость в этом, - хорошая вещь.

...