3

I currently display particle effects once my sprite collides with another sprite in-game.

I have this snippet of code:

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

The particle I created has a birthrate of 1000 particles with a maximum of 100. I set the position of the particle emitter node to where my sprite is currently on screen. Then, I add it as a child of the particle layer node.

My question is, do I have to manually remove the particle emitter node from its parent after it's finished? Or does Sprite Kit automatically remove it after it has finished playing?

Since my project is designed to have the sprites collide with each other a lot, I want to make sure if I still need to handle this manually to prevent memory leaks (the particle layer having a lot of child emitter nodes that are finished playing already)

CodeSmile
  • 64,284
  • 20
  • 132
  • 217
aresz
  • 2,589
  • 6
  • 34
  • 51
  • 1
    you have to remove it yourself. – hamobi Feb 03 '15 at 19:52
  • @hamobi thanks for the comment. is there an event/method that gets triggered when the emitter node is done playing so that I can detect when to remove it? – aresz Feb 03 '15 at 21:52
  • No I don't think so.. I just remove it after a certain amount of time using an SKAction – hamobi Feb 03 '15 at 22:03

2 Answers2

1

I actually recommend that you do remove the emitter. I had an issue in my game recently where it would start lagging really badly because I wasn't removing emitters. It was an issue that I was able to 100% reproduce when emitters were added, so I know for a fact they were the sole reason for the frame rate drop. It took about 20 un-removed emitters before I started seeing a lag.

It's actually pretty easy. You can create an SKAction Sequence containing a wait action (1 sec or just a bit over the length of your effect) and a removeFromParent action.

That will get rid of it just about after it's done, and ensure your frame rate doesn't drop.

David Baez
  • 1,208
  • 1
  • 14
  • 26
0

The short answer is no you don't need to worry about it in your case. But if the particle emitter is off the screen or running permanently it becomes more of an issue. When the scene is deallocated the SKEmitterNode will be removed automatically. Because an SKEMitterNode is an SKNode that is inserted into the node tree.

However, If you want to be extra careful, you can manually and recursively stop all actions and emitters before the scene deallocates with the following method. I was having problems with delayed SKActions firing after the scene was deallocated and crashing my app, so I manually stop them all before the scene is deallocated.

Keep a reference to the old scene and call this on the scene:

+(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];

}

Then, use it in your GameViewController or wherever you are changing scenes:

SKScene *oldScene = skView.scene;
[skView presentScene:newScene transition:nil];
if (oldScene) 
   [PCUtils recursivelyStopAndRemoveNode:oldScene];
Patrick Collins
  • 4,046
  • 3
  • 26
  • 29