Search code examples
iosmemorysprite-kittexture-atlassktextureatlas

Why is SpriteKit loading all device sizes (~ipad and @2x~ipad) textures into memory?


I'm loading textures into SpriteKit for use in an animation using the following code -

NSMutableArray *animFrames = [NSMutableArray array];
SKTextureAtlas *animTextureAtlas = [SKTextureAtlas atlasNamed: @"bearAnimation"];

for (int i = 1; i < animTextureAtlas.textureNames.count / 3; i++) {
    NSString *texture = [NSString stringWithFormat:@"image%04d", i];
    [animFrames addObject:[animTextureAtlas textureNamed:texture]];
}

// This is a strong property of an NSArray where I store frames of animation
self.bearAnimationFrames = animFrames;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    [SKTexture preloadTextures:self.bearAnimationFrames withCompletionHandler:^{}];
});

My issue is that using the above code on an atlas that contains three versions of each image for retina iPad, non-retina iPad and retina iPhone results in the app using memory for all of them. Not just the ones it needs.

How can I make it so that the only textures loaded into memory are the ones the device the app is running on needs?


Solution

  • First, I read Noah Witherspoon's answer "Set up separate atlases, one for each type of screen."

    Next, I see that you still had more questions "Anyway how do I go about accessing an atlas based on the category of device used? Should I just be checking for an iPad or iPhone and then breaking down the iPad section into are you an iPad 2?"

    I think that Noah was trying to point out that instead of creating 1 big atlas that contains all images for 3 different versions of screen resolutions, your code should probably create 3 separate atlases (with 3 separate names) : one of each version of the screen resolution.

    If you go with his approach, then in your code, during the initialization phase of or your app, perhaps, you could check for the device (or the screen resolution), and then your code can first create only 1 proper atlas for that one particular screen resolution, and after that you code can load that atlas onto RAM. This way, your app only creates and loads 1 set of images for 1 particular device onto RAM instead of loading all 3 sets of images onto RAM.

    So, if you go with this strategy, you can save a large amount of RAM that your app uses at runtime. This is very important and valuable. I have seen many apps crash after running for awhile on the iPad because they use too much RAM, especially in iOS 9.0 and newer.


    If you have a better solution, please share with us.

    I am a new game developer, and am still trying to learn a lot of new techniques to improve my game. So, I would greatly appreciate new tips or lessons on this forum...