0

I am trying to create 2d platform game using SpriteKit. The game contains 21 levels, this means 21 scenes and 21 tilesets as well. Each scene contains several tilenodes, all of which uses only 1 tileset. At some point I found that my game consume almost 2GB of memory and sometimes being terminated due to memory issue.

enter image description here

I started investigation of reasons for this memory leaks using instruments. I found 4 leaks which shown on attached screenshot. Responsible library is JavaScriptCore, I have no idea what the hell that means.

enter image description here

So, I continue investigation and try to remove blocks of code and assets from project in order to understand what going on.

At the end my project contained:

  1. GameViewController which is looks exactly like GameViewController from XCode template.
  2. Empty subclass of SKScene
  3. 1 Scene
  4. 21 Tilesets

Code of the GameViewController:

class GameViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    if let scene = GKScene(fileNamed: "GameScene") {
        if let sceneNode = scene.rootNode as! SKScene? {
            sceneNode.scaleMode = .aspectFill
            if let view = self.view as! SKView? {
                view.presentScene(sceneNode)
                view.ignoresSiblingOrder = true
            }
        }
    }
}


override var shouldAutorotate: Bool {
    return true
}


override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone {
        return .allButUpsideDown
    } else {
        return .all
    }
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}


override var prefersStatusBarHidden: Bool {
    return true
}

}

So, no code which can cause leaks and the game still consume 2GB in peaks. And only when I remove all tilesets from project except one which is required for level - the memory consumption became normal, like ~200mb.

enter image description here

My guess that the SpriteKit load all tilesets into memory despite all tilenodes of the scene using only 1 tileset.

Also, game works well if I put tilesets back to the project and remove all tilenodes from scene.

My questition is how to properly manage this situation?

Thank you!

Update1: Memory Graph is attached Update2: GameViewController code is provided

enter image description here

acidbeast
  • 43
  • 8
  • you can debug memory graph and track down those purple '!'. It will tell you where the leaks from. – E.Coms Mar 09 '19 at 15:05
  • I did it as well, graph shows nothing useful for me. I attached graph screenshot to post. – acidbeast Mar 09 '19 at 16:13
  • 1
    Without code your question is the equivalent of snuffle. We're not mind readers. – Magnas Mar 09 '19 at 17:04
  • 1
    You are supposed to free of all those pink purple "!". Sometimes, like missing a `weak`. Sometimes you are calling a system function in an imperfect manner. But at first try to remove all those `!`. – E.Coms Mar 09 '19 at 18:07
  • @Magnas I update post with GameViewController, it is really looks like default GameViewController from XCode SpriteKit Game Template – acidbeast Mar 09 '19 at 18:10
  • @E.Coms Yes, I know about strong and weak references. When i tried to reproduce problem i did remove all my code from project and insert default GameViewController from XCode SpriteKit Game Template instead, to show that the project have no code which can cause memory leaks. – acidbeast Mar 09 '19 at 18:13
  • if its system function call, you have to add class by class and function by function until you see the "!" comes out. Then you will know which step introducing the issue. – E.Coms Mar 09 '19 at 18:15
  • @E.Coms I do not need put my code back to project, because memory leaks even with default GameViewController which is load my scene with tilenodes. There is no any other code in the project except default GameViewController. – acidbeast Mar 09 '19 at 18:20
  • Do you know specific line? – E.Coms Mar 09 '19 at 18:28
  • You can add an instance value for management. That means to extract a local temp variable to store it somewhere – E.Coms Mar 09 '19 at 18:32
  • @E.Coms unfortunately, leaks on the graph does not refer to any line of code or something else. :( – acidbeast Mar 09 '19 at 19:03
  • Not for graph. Just delete some code then add back till you see the leak. – E.Coms Mar 09 '19 at 19:17
  • Why don't you try reading a tile node programmatically for each level, then? – El Tomato Mar 10 '19 at 06:46
  • 2
    The SKTileMapNode and its surrounding features are incredibly buggy. I am not surprised you are having problems with this. I have first-hand experience, and I can tell you, I would recommend staying away from this section of SpriteKit. You will have a much easier time writing all your own code to function in the place of SKTileMapNodes (And the surrounding features). – E. Huckabee Mar 12 '19 at 08:57
  • @El Tomato Yep, i moved all tile nodes to dedicated scene file and tried to load this file programmatically and then move nodes to main scene. But unfortunately, memory leaks anyway exactly when i load scene with tile nodes. – acidbeast Mar 27 '19 at 05:49

2 Answers2

0

Try this:

open Info.plist file, add a new row,

key: "PrefersOpenGL" type: "Boolean" value: "YES"

Sunil Sharma
  • 2,653
  • 1
  • 25
  • 36
Ben
  • 1
  • SpriteKit is now defaulting to Metal mode, switching back to OpenGL compat mode could be useful to some debugging purposes but it is not a solution in a shipping product. – MoDJ May 27 '19 at 19:26
0

I found the cause of that problem. All my tilesets are in different files, each tileset has own sks file. When i moved all tilesets into one sks file the problem is gone. I assume that at some point game try to load all exist tilesets for every sks file and takes too much memory.

acidbeast
  • 43
  • 8