Нужно ли вручную удалять узел эмиттера из родительского узла после завершения воспроизведения?

В настоящее время я отображаю эффекты частиц, когда мой спрайт сталкивается с другим спрайтом в игре.

У меня есть этот фрагмент кода:

let sparkParticle = SKEmitterNode(fileNamed: "SparkParticle.sks")
if sparkParticle.parent == nil
{
    sparkParticle.position = mySprite.position
    self._particleLayer.addChild(sparkParticle)
}
sparkParticle.resetSimulation()

Частица, которую я создал, имеет скорость рождения 1000 частиц, максимум 100. Я установил положение узла-эмиттера частиц, где мой спрайт в данный момент находится на экране. Затем я добавляю его как дочерний узел узла слоя частиц.

У меня вопрос, нужно ли вручную удалять узел эмиттера частиц из его родителя после его завершения? Или Sprite Kit автоматически удаляет его после завершения воспроизведения?

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

2 ответа

Решение

Короткий ответ: нет, вам не нужно беспокоиться об этом в вашем случае. Но если эмиттер частиц находится вне экрана или работает постоянно, это становится более серьезной проблемой. Когда сцена будет освобождена, SKEmitterNode будет удален автоматически. Потому что SKEMitterNode - это SKNode, который вставляется в дерево узлов.

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

Сохраните ссылку на старую сцену и назовите ее на сцене:

+(void)recursivelyStopAndRemoveNode:(SKNode*)node {

    // recursively call all children
    for (SKNode *childNode in [node children]) {
        [PCUtils recursivelyStopAndRemoveNode:childNode];
    }

    // stop emitters
    if ( [node isKindOfClass:[SKEmitterNode class]]) {
        SKEmitterNode* sken = (SKEmitterNode*)node;
        sken.targetNode = nil;
        sken.particleBirthRate = 0;
        NSLog(@"stopping emitter %@", node.name);
    }

    // stop any running actions
    [node removeAllActions];

    // remove me from my parent.
    [node removeFromParent];

}

Затем используйте его в вашем GameViewController или везде, где вы меняете сцены:

SKScene *oldScene = skView.scene;
[skView presentScene:newScene transition:nil];
if (oldScene) 
   [PCUtils recursivelyStopAndRemoveNode:oldScene];

Я действительно рекомендую вам удалить излучатель. Недавно у меня была проблема в моей игре, из-за которой она начинала очень сильно отставать, потому что я не удалял излучатели. Это была проблема, которую я смог воспроизвести на 100% при добавлении излучателей, поэтому я точно знаю, что они были единственной причиной снижения частоты кадров. Потребовалось около 20 неснятых излучателей, прежде чем я начал видеть отставание.

Это на самом деле довольно легко. Вы можете создать последовательность SKAction, содержащую действие ожидания (1 секунда или чуть-чуть больше длины эффекта) и действие removeFromParent.

Это избавит от него сразу после того, как это будет сделано, и гарантирует, что ваша частота кадров не упадет.

Другие вопросы по тегам