Learn iOS with Examples, Code Snippets and Video Tutorials

Properly removing nodes with Sprite Kit

Properly removing nodes with Sprite Kit
May 6, 2014 Justin

The word “properly” might be an overstatement as there could be even more proper ways to remove a node, but I noticed something VERY strange this morning with Sprite Kit. My latest iOS Starter Kit, (shameless plug) has an object class used for a lot of things, enemies, trees, whatever you can think of that might receive damage from a character and eventually bust. So I thought it might be nice to add an option to the kit where the object/enemy can recover health over time. Easy, breezy code: Every second add back some decimal amount to the current health of the object. For those curious it looks something like this…

 

So I call gainBackHealth which checks to see if the object should gain back some health, if so, it adds the gainHealth amount (established elsewhere) and then I use  performSelector and do it all again one second later.  So for any object that will gain back health over time, this method is running every second.

So I build the app, and magically I’ve created a harder, “bossier” character to kill.  Too hard actually. I died trying to kill the character and the level reset. But here’s where it gets interesting. When the level started over AFTER removing every node, I was seeing the NSLog statement running twice every second. Odd. Then I went to go kill the enemy, and now I’m seeing this happen in the Output Window…

 

I’m doling out some damage to the enemy, and its registering the pain, but somewhere out there in the Sprite Kit world an object still has 10 for their current health. And only one object was ever set to gain back health over time. So what happened was the performSelector was never cancelled on the original enemy I tried to kill before I died and the level was reset.

So lets look at some of my reset code…

As you can see, I go through every child in myWorld and remove them using  enumerateChildNodesWithName:@”*” , and then finally I remove myWorld just to be sure everything is cleared out. At this point, nothing is left in the scene, and my assumption was that the world has been cleared of any “thought” processes (e.g. performSelectors ). GUESS NOT! So here’s the conclusion, I needed to add this line…  [NSObject cancelPreviousPerformRequestsWithTarget:node];

 

This was a tad surprising since I assumed that removing a node would automatically “clean it up” so to speak and cancel those perform requests, but hey, its not much more work to add the line above.

Hope this helps someone else out there.

 

Justin Dike is the owner and lead developer at CartoonSmart.com. He's taught hundreds of hours of game development video tutorials, covering everything from coding to art. These days he's working mostly on Swift and Sprite Kit tutorials, which often lead into highly polished iOS / tvOS Starter Kits, which require no programming at all, but are capable of making nearly any type game! Yeah, you read that write. You can also find Justin at the official CartoonSmart Podcast

0 Comments

Leave a reply

Your email address will not be published. Required fields are marked *

*

Check out our premium Swift and Sprite Kit Tutorial content!

Visit CartoonSmart.com