Sprite Kit memory issues

Hello,

first of all – thank you for 2D iOS and tvOS Games by Tutorials book – it is really helpfull :slightly_smiling:

So I created a small game with several scenes and facing some memory issues:

  • The first issue I already solved – a scene was not deallocated after transition to another scene. I didn’t have any strong references inside of this scene, but the deinit was simply not called at all. I present a scene like in the tutorial:

      if let scene = GameScene(fileNamed:"GameScene") {
          let transition = SKTransition.crossFadeWithDuration(1.0)
          scene.scaleMode = .AspectFill
          scene.backgroundColor = SKColor.redColor()
          self.view?.presentScene(scene, transition: transition)
      }
    

    So I solved this by overriding willMoveFromView. In this method I iterate through all nodes and remove they from parent node. I also stop all actions and remove them. Finally I call removeFromParent() method. After this the deinit method is called when I present the next scene. This approach was not obvious for me, because it is not used in the tutorials and there are no issues with memory usage.

  • Though all scenes and nodes are being deallocated now (I just added debugPrint("\(NSStringFromClass(self.dynamicType)).deinit") in deinit method of each custom class to double check whether deinit is called), I still have a memory issue when I simply switch between two scenes (simply scenes with 3-4 sprite nodes) and each scene presents the next one like mentioned above:

    Even when I simply stay in one scene the memory usage increases:


    So I tried to find memory leaks with Instruments and there are some of them (at this point I simply display a start scene with couple of buttons and two basic animations):

    It seems like the problem is in MetalKit, but I don’t know how to fix this and which part of my game causes this issue.

Do you have any advices where I can start searching?
Thanks

It seems like skView.showsPhysics = true caused continuous memory consumption growth. After I removed this line the mentioned memory leaks were also gone.

The issue I still have – memory is not completely freed after scene is deallocated. After I switch between two scenes several times I get following:

I also tried to invoke memory warning in simulator, but nothing happened.

Are you usking SKActions to play sound effects by chance?

I think there were a couple of things that prevented memory of being deallocated. But I solved this memory issue finally. Changes I made:

  • SKTexture(imageNamed:) → SKTexture(image:) (when I can’t use an atlas)
  • double check all closures and pass weak or unowned self
  • remove all actions, delegates, and child-nodes etc. in willMoveFromView function of the scene
  • remove all components from GKComponentSystem in willMoveFromView function
  • replace all SKAction.playSoundFileNamed with runBlock actions which start AVAudioPlayer
1 Like

For my part, the main culprit is the SKTexture(imageNamed:), this loads a texture into memory and doesn’t deallocate it even if the node is removed from the scene.
You have to manually re-remove all nodes from the scene (in whichever function that signals the exit of the actual scene), and then set the scene to nil.

I wrote a small loop-function that just loops through childs and remove every node, after that setting the scene to nil and doing another presentScene: (presenting an empty scene forces the current one to deallocate).
This solved my memory leak problems.

If you have a predefined number of nodes, you can reset their textures to an empty image as well.

@gershengoren Can you show some of your code for your willMoveFromView function? I’m running into some of the same problems.