The one year game develpoment duel
Feb

3

2015

Saving Game Data in SpriteKit

When searching for tips on how to save game data in SpriteKit, most posts explain how to save one variable (high score, for example). In that regard, this Thinking Swiftly post was extremely helpful, and is where a majority of the code below comes from. I just wanted to extend that post, and look at how an entire object could be saved in a self contained way.

NOTE: This article has been updated. Refer to SpriteKit Saving with Swift 3

A class will hold a singleton which will automatically load the first time it is called. No initialization from the outside needed.

// Access a variable. Will lazy load the first time.

GameData.sharedInstance.variableA

Likewise, to save, we simply call save. Below, we’ll change a value, and save it out.

// Change a variable, and then save.

GameData.sharedInstance.variableA = 2
GameData.sharedInstance.save()

The only major difference from other posts I’ve seen is in the actual save method. Instead of encoding each variable, I am just encoding the entire object. Note: This only works with standard variable types — if you need to save out a custom class, you have to make the class extend NSCoding.

let saveData = NSKeyedArchiver.archivedDataWithRootObject(self.scores);

// Becomes

let saveData = NSKeyedArchiver.archivedDataWithRootObject(GameData.sharedInstance);

Have a look at the entire GameData class below, which should act as a self contained, lazy loading class to hold game data of standard variable types.

 

12 of you did not hold your tongue!
  1. […] year I wrote about saving game data in SpriteKit, and that code is now completely out of date. Swift 3 has brought about all sorts of fun changes, […]

  2. I have a real question now: In your code, the file you are copying to “GameData.plist” is called “DefaultFile.plist.” However, there is no such thing as “DefaultFile.plist”. I assume this is just a placeholder, so what do put there instead? I tried “Info.plist”, but that gives me an error.

    Thanks

    • What I don’t understand is how a new file is being created by copying “DefaultFile.plist” to “HighScores.plist”. Don’t we need to create “HighScores.plist” first?

      • Hmm, I’m not 100% sure why DefaultFile works, but it does. I’m going to dig around and see if it is only there in certain projects. I can tell you that it is not visible in my project folder, so I assume it is always an underlying file. Seems all answers on stack overflow assume it is present as well. What platform are you working with?

        • What I decided to do is make my own file called “DefaultGameData” and replace “DefaultFile” in code with “DefaultGameData.” Also, I had to update some of the code with swift 2 and I used your gist in the comment down below. After a few hours of testing and googling, I got it all working. If I post my code online, I’ll put a link here so that people can see how to implement your class in swift 2.

          Thank you SO MUCH for this great tutorial. It makes saving data in SpriteKit so easy!

          Thanks again,
          Noah

  3. I know this has been posted for a while…I am just having one problem.

    When I try to call GameData.save(), Xcode thinks the save() function has a parameter of type “GameData.” Additionally, Xcode gives the following error: “Use of instance member ‘save’ on type ‘GameData’; did you mean to use a value of type ‘GameData’ instead?”

    I try putting GameData.save(GameData). When I do that, however, Xcode throws the same error as above.

    I can’t figure out how to make it work. thanks

    • Alright I am stupid, literally caught the mistake two seconds later…Forgot to use .sharedInstance. That fixes it! Thanks again for the great tutorial. It works nicely.

  4. Is it possible to save entire objects with this method? I’m trying to save my entire player object and it seems to work but none of the custom properties I have on him are saving (like health) It’s just a subclassed SKNode with a few properties. Trying to save the entire thing instead of each variable.

  5. This seems really cool but I can’t seem to get it to work. It’s not giving me any errors either. Looks like it’s not saving, but it is creating the plist file. Really frustrating that it”s not giving any errors. Has anything changed with the latest versions of Xcode/ios?

    • The problem is likely how I glossed over the need for NSCoding. After I wrote this, I realized that you have to fully implement encodeWithCoder, so the line above that encodes the entire sharedInstance is wrong. While you can save the entire shared instance in the save() function, you still have to encode each member variable individually. You can see this example as a reference: http://nshipster.com/nscoding/. I’ve also uploaded a gist of my current working example here: https://gist.github.com/veeneck/724ad57982e7fa6214a3

      • Nice! Thanks for spending time to help me out. Works great.

  6. […] Save game […]


Speak freely