3

I'm designing a game in iOS Swift.

I have a large texture-atlas of about 100 1920x1080p PNG's. When I call the functions it crashes the app due to memory pressure. When I disable the function my app runs just fine.

Can I prevent this crash by editing my code or is my texture-atlas just too big?

Code:

var waterWave: SKSpriteNode!
var waterWalkingFrames : [SKTexture]!

func addWater() {

    let waterAnimatedAtlas = SKTextureAtlas(named: "water.atlas")
    var waterFrames = [SKTexture]()

    let numImages = waterAnimatedAtlas.textureNames.count

    for var i=0; i<numImages; i++ {
        let waterTextureName = "water_000\(i)"
        waterFrames.append(waterAnimatedAtlas.textureNamed(waterTextureName))
    }

    self.waterWalkingFrames = waterFrames

    let firstFrame = waterWalkingFrames[0]
    self.water = SKSpriteNode(texture: firstFrame)

    self.water.anchorPoint = CGPointMake(0.5, 0.5)
    self.water.position = CGPointMake(CGRectGetMidX(self.frame), self.runningBar.position.y + (self.runningBar.size.height / 2) + 5)
    self.water.size.width = self.frame.size.width
    self.water.size.height = self.frame.size.height
    self.water.zPosition = 7

    self.addChild(self.water)

    waterAnimation()
}

func waterAnimation() {

    self.water.runAction(SKAction.repeatActionForever(
        SKAction.animateWithTextures(waterWalkingFrames, timePerFrame: (1 / 60), resize: false, restore: true)), withKey:"surferBasic")
}
Nick Groeneveld
  • 895
  • 6
  • 18
  • 100 high-res images will consume a lot of device's memory. Even if you won't use a texture atlas your program will probably reach the memory limit. Also note that a texture atlas is limited to 4096x4096 resolution (ios8+) and 2048x2048 (For iOS < 8). – giorashc May 31 '15 at 08:45
  • 1
    An iOS app is limited to a max of about 650 megs of memory in use at any one time, but the system will likely kill your app before you reach that limit. You have to start over with a different approach like loading frames one at a time and not holding them all in memory. – MoDJ Apr 10 '16 at 22:48

1 Answers1

1

Animation like that would be always expensive even if you optimize textures in some way (e.g. changing texture format). 1920x1080px texture occupies about 8 megabytes if using standard RGBA8888 format when stored in RAM memory and as you said, because of device memory limitation, the app will crash at some point.

In this situation, if your animation allows you to do this, a good way would be to make a video of it, and then to use SKVideoNode to play it. This is even recommended in docs just because using textures can be expensive in some situations:

Like any other node, you can put the movie node anywhere inside the node tree and Sprite Kit will render it properly. For example, you might use a video node to animate some visual behaviors that would be expensive to define using a collection of textures.

This would be a suitable way for background animations, cut scenes, intros ...

For looping a video you can use AVPlayer to initialize SKVideoNode with it. Read more here. I suggest you to do this because SKVideoNode is limited to just play() and pause() methods for controlling video playback.

Hope this helps and make some sense!

Community
  • 1
  • 1
Whirlwind
  • 14,286
  • 11
  • 68
  • 157