Reputation: 71
I am having trouble caching a large texture atlas (almost full 2048x2048) and using it for animatewithtextures. It lags initially on the first load. After that it is ok. With all of my other atlases I just put them in a singleton and save them off using the method from the following link: https://www.codeandweb.com/blog/2013/09/23/spritekit-animations-and-textureatlases self.atlas = [SKTextureAtlas atlasNamed:SPRITES_ATLAS_NAME]
It seems as though it is loading and then unloading the texture atlas in memory. Has anyone else experienced this? Using Swift 1.2, SpriteKit, Texture Packer
Upvotes: 1
Views: 802
Reputation: 71
I did end up finding a solution to this. All you have to do is add an item to the scene before runtime to make sure it decompresses the atlas. I wrote a function to do this to all my atlases in the atlas/texture controller. Apple said there is no built in function to do this, and the preload function will not perform the decompression.
Upvotes: 1
Reputation: 11696
If you are using a singleton to store all your animations, I suggest organizing it with these examples in mind.
Singleton Header File
-(void)loadPlayer0Atlas;
@property (strong) SKTextureAtlas *player0Atlas;
@property (strong) SKAction *player0_walk;
@property (strong) SKAction *player0_jump;
@property (strong) SKAction *player0_shoot;
Singleton Implementation File
-(void)loadPlayer0Atlas {
if(self.player0Atlas == nil) {
NSLog(@"loading player0AtlasLoaded");
self.player0Atlas = [SKTextureAtlas atlasNamed:PLAYER0ATLAS_ATLAS_NAME];
[SKTextureAtlas preloadTextureAtlases:[NSArray arrayWithObject:self.player0Atlas] withCompletionHandler:^{
[self loadPlayer0Assets];
}];
} else {
NSLog(@"no load needed for player0AtlasLoaded");
[[NSNotificationCenter defaultCenter]postNotificationName:@"player0AtlasLoaded" object:self];
}
}
-(void)loadPlayer0Assets {
self.player0_walk = [SKAction repeatActionForever:[SKAction animateWithTextures:PLAYER0ATLAS_ANIM_WALK timePerFrame:0.1]];
self.player0_jump = [SKAction animateWithTextures:PLAYER0ATLAS_ANIM_JUMP timePerFrame:0.05];
self.player0_shoot = [SKAction repeatActionForever:[SKAction animateWithTextures:PLAYER0ATLAS_ANIM_SHOOT timePerFrame:0.1]];
[[NSNotificationCenter defaultCenter]postNotificationName:@"player0AtlasLoaded" object:self];
}
The strong class properties keep a reference to your atlas and animations. You can call the loadPlayer0Atlas method to load the atlas and animations. Once loaded, a NSNotification message is delivered letting you know in your (for example) GameScene.
You would call the animations like this:
[playerNode runAction:[singleton player0_walk] withKey:@"animation"];
Upvotes: 0
Reputation: 13675
By using the Singleton pattern in your GameTextures class you are probably just keeping away self.explosionAtlas
from being initialized twice. But I think you are not preloading textures actually. You have to preload them first and then keep them from being released by holding strong reference to them like @sangony pointed. Storing reference like self.explosionAtlas
does not automatically preload textures from that atlas into memory. You can check this in debug navigator by looking at memory consumption when you preload textures manually into array or using method like + preloadTextureAtlases:withCompletionHandler: vs doing something like self.atlas = [SKTextureAtlas atlasNamed...]
One thing I would do is to remove code related to that animation completely to see if app lags at start when the scene is presented. Just to be sure where the problem is.
Also check your timePerFrame parameter... Don't set it too low... If you are using 39 images just for one explosion I think you should try with little less frames and setting timePerFrame parameter to higher value. I have an explosion with 10 images with timePerFrame set to 0.06 and still looks great. You are certainly aware that devices have limited memory...iPhone 4s has 512 megabytes of RAM memory but it will crash when memory consumption is about 200 - 250 MB. So be careful with big animations/textures because textures consume most of app's memory . Check this out
To calculate how much image will take into memory you can read here.
Note that you can make great explosions with SKEmitterNode if you decide to give up on current animations, but I still think that you are not caching textures properly and they are not ready before animation is called (as well as you are using small timePerFrame interval, like 0.033 or something like that).
Hope this will lead you somewhere.
Upvotes: 1