Reputation: 31
I'm using SpriteKit for a 2D game and have an array of images for a simple animation.
var hyperLeapArray: [SKTexture] = []
for i in 0 ..< 90 {
hyperLeapArray.append(SKTexture(imageNamed: "hyper_leap_\(i)"))
}
let animation = SKA.animate(with: hyperLeapArray, timePerFrame: 0.03)
self.animationHost.run(SKAction.repeatForever(animation)) // Plays the animaion on a loop.
The first time this is executed - FPS drops to ~20 and then smoothly stabilizes up to 60. To avoid this, I've decided to use SKTexture.preload
method before playing the animation.
Task.init {
await SKTexture.preload(hyperLeapArray)
}
And, on a simulator it worked fine, FPS are still dropping, but for acceptable > ~35 rate. But this solution caused another issue with memory on a real device. After investigating, I realized that calling SKTexture.preload
- fills the memory up to ~1.5GB - which is enormous and keeps that memory in use before the animation is cashed. Original 90 images weight only 12Mb, I have no idea how this is growing to the enormous amount of space.
What I've tried:
func preload(index: Int, array: [SKTexture]) {
if (index < array.count) {
array[index].preload {
print("Preloaded \(index)")
sleep(1)
preload(index: index + 1, array: array)
}
} else {
print("Done")
}
}
But nothing helped so far.
Any ideas on
Here is full code snippet if you'd like to reproduce it locally:
final class TempScene: SKScene {
private var animationHost: SKSpriteNode!
private var hyperLeapAnimation: Animation!
convenience init(test: Bool) {
self.init(size: FULL_SCREEN_SIZE)
let center = CGPoint(x: frame.width / 2, y: frame.height / 2)
animationHost = SKSpriteNode(color: .clear, size: FULL_SCREEN_SIZE)
animationHost.position = center
animationHost.zPosition = 110
addChild(animationHost)
var hyperLeapTextures: [SKTexture] = []
for i in 0 ..< 90 {
// You can use any texture instead.
hyperLeapTextures.append(SKTexture(imageNamed: "hyper_leap_\(i)"))
}
Task.init {
await SKTexture.preload(hyperLeapTextures)
}
let animation = SKAction.animate(with: hyperLeapTextures, timePerFrame: 0.03)
animationHost.run(SKAction.sequence([SKAction.wait(forDuration: 6),
SKAction.repeatForever(animation)]))
}
}
Upvotes: 2
Views: 110
Reputation: 31
After investigating, I've realized that the reason was that no matter how much a picture file size is, the main thing that matters is picture resolution and in my case, a single image memory size was 32x1536×2048 / 8 / 1024 / 1024 = 12Mb. (Where 1536×2048 is the actual picture size). And I had at least 100 frames.
Unfortunately, it seems like there is no way to avoid memory overflow error in such cases :/
Frame animation should be used for small images, but for big ones the only acceptable way is to replace frame animation with a video file using SKVideoNode.
Upvotes: 1