4

I have a problem getting a texture atlas to free. Currently I have a SpriteKit game where a player can change his character. Right now I have the atlas's in a Global shared instance like so.

let char0Atlas: SKTextureAtlas = SKTextureAtlas(named: "Atlas/iPhone/char0")
let char1Atlas: SKTextureAtlas = SKTextureAtlas(named: "Atlas/iPhone/char1")
let char2Atlas: SKTextureAtlas = SKTextureAtlas(named: "Atlas/iPhone/char2")

Each character you can change to has their own texture atlas. I fetch player movement, idle, and jump animations from that characters atlas with a method like this:

func charAnimation(char: CharEnum) -> [SKTexture] {
    var temp: [SKTexture] = []
    var name: String = ""

    let atlas: SKTextureAtlas = char.atlasForChar()

    for i in 1...20 {
        if i > 9 { name = "char_\(charId)_idle_00\(i)" }
        else { name = "char_\(charId)_idle_000\(i)" }
        temp.append(atlas.textureNamed(name))
    }

    return temp
}

And that is stored in an array instance variable in the player sprite node class. So every time a character is changed, these frames are replaced with the new frames, so the old ones should be freed correct?

class PlayerNode: SpriteNode {
    private var currentAnimation: [SKTexture] = []
    private var animations: (idle: [SKTexture], run: [SKTexture], jump: [SKTexture]) = PlayerController.animationsForHero(.CharOne)
}

Also, when the player switches characters, I use this to preload the texture atlas:

SKTextureAtlas.preloadTextureAtlases([char.atlasForHero()], withCompletionHandler: { () -> Void in
            updateChar()
        })

Why is SpriteKit never freeing the memory from the previous character animations? If the player switches to new characters, the memory constantly increases and crashes the app. If a character who was already chosen in that session is chosen again, the memory does not increase. This shows a memory leak. The characters animations are not being freed. Why?

I understand SpriteKit is supposed to take care of this stuff by itself, so that's why it's confusing. Is there absolutely no way to free a texture atlas myself manually?

Thanks!

datWooWoo
  • 843
  • 1
  • 12
  • 42
  • 1
    i am not sure but may be you are fetching textures again and again from SKTextureAtlas save your textures as a NSDictionary or singleton and fetch them only once from texture atlas and secondly if you want to clear a texture from memory remove its textureAtlas not texture that would remove it from memory too – dragoneye Jul 29 '15 at 09:29

1 Answers1

3

@dragoneye first point is correct: you have to preload SKTextureAtlas only once.

Have a look at Apple's documentation Working with Sprites:

-

  1. Preloading Textures Into Memory
  2. Removing a Texture From Memory

Then if memory is not freed this may be because there still exist references to SKTexture as pointed by second point:

After a texture is loaded into the graphics hardware’s memory, it stays in memory until the referencing SKTexture object is deleted. This means that between levels (or in a dynamic game), you may need to make sure a texture object is deleted. Delete a SKTexture object object by removing any strong references to it, including:

  • All texture references from SKSpriteNode and SKEffectNode objects in your game
  • Any strong references to the texture in your own code
  • An SKTextureAtlas object that was used to create the texture object
Dominique Vial
  • 3,729
  • 2
  • 25
  • 45
  • "An SKTextureAtlas object that was used to create the texture object" So that means keeping a singleton variable of each atlas is keeping it from freeing? Does that mean every time I fetch a texture I should fetch the atlas as well? – datWooWoo Aug 06 '15 at 17:01
  • Yes for the first question: if the reference to the `SKTextureAtlas` is strong. And I don't understand the second question. – Dominique Vial Aug 06 '15 at 17:30
  • I have a question: why do you reload texture atlas when the player switches characters? Is there any reason? – Dominique Vial Aug 06 '15 at 17:33
  • Errrr ya sorry. What I mean by "fetch" is when creating a sprite or updating the player animations for the new character, should I always instantiate a new texture atlas and new texture like so: SKTextureAtlas(named: whatever).textureNamed(name) instead of referring to any kind of singleton? "why do you reload texture atlas when the player switches characters? Is there any reason?" I can't preload all the character animations on startup, the iPhone 4s can't do handle it and will crash. So I have to do it when the player changes. – datWooWoo Aug 06 '15 at 17:38
  • If `SKTexture` from a `SKTextureAtlas` you have to remove the `SKTextureAtlas`. So if you need another `SKTexture` from the `SKTextureAtlas` then you have to reload it. It's my understanding. – Dominique Vial Aug 06 '15 at 17:51
  • Here is an answer that may interest you: http://stackoverflow.com/a/19356341/540780 – Dominique Vial Aug 06 '15 at 17:57
  • Okay so if I don't have a singleton Atlas, then every time I need to create and SpriteNode and add it to the scene it's going to do a little "freeze stutter" EVEN if I preload the atlas. So how do you do this? It doesn't make any sense. If you have a singleton then it won't release from memory. If you don't, then the game will lag when trying to add a SpriteNode to the scene because it has to instantiate another atlas object. Don't get it... – datWooWoo Aug 06 '15 at 20:08
  • Let's read the answer I post above as it's about his kind of situation. – Dominique Vial Aug 06 '15 at 20:31
  • Thanks for trying to help, but it's not. That post above talks about 1) Some optimization techniques for atlas's that reduces memory and speeds up drawing 2) Component-Oriented programming suggestions. It has nothing to do with how to setup, manage, and fetch assets from an atlas correctly and without lag. I've seen many example tutorials that put the atlas as a constant in a singleton...soooo ya I'm pretty lost. – datWooWoo Aug 06 '15 at 21:42
  • The post also mention **atlas usage**, that's why I linked to it. Anyway here is another post that lay better help you: http://stackoverflow.com/a/21765524/540780 – Dominique Vial Aug 06 '15 at 21:45
  • By the way, are your images compressed? – Dominique Vial Aug 06 '15 at 21:46
  • I don't know the gameplay you want to create but maybe there is some tricks you can use to avoid lag. For example when the player switches characters launch an animation and stop it once atlas load has completed. – Dominique Vial Aug 06 '15 at 21:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/85351/discussion-between-domsware-and-lespommes). – Dominique Vial Aug 06 '15 at 21:59