0

I have the function that moves an object and runs animation on move:

func animateMove(move: MoveTo, completion: () -> ()) {
    let object = move.object
    let spriteName = "\(object.spriteName)\(move.direction.name)"

    let textures = TextureCache.loadTextures(spriteName)
    let animate = SKAction.animateWithTextures(textures, timePerFrame: moveDuration/NSTimeInterval(textures.count))

    let point = pointForColumn(move.column, row: move.row)
    let move = SKAction.moveTo(point, duration: moveDuration)
    move.timingMode = .Linear

    let group = SKAction.group([move, animate])
    object.sprite!.removeAllActions()
    object.sprite!.runAction(group, completion: completion)
}

Also I have the cacher:

class TextureCache {
...

static func loadTextures(name: String) -> [SKTexture] {
    let atlas = "\(name).atlas"
    return TextureCache.sharedInstance.loadTexturesFromAtlas(atlas, name: name)
}

private func loadTexturesFromAtlas(atlas: String, name: String) -> [SKTexture] {
    if let textures = textureDictionary["\(atlas):\(name)"] {
        return textures
    }

    let textureAtlas = SKTextureAtlas(named: atlas)
    var textures = [SKTexture]()
    for i in 0..<textureAtlas.textureNames.count {
        textures.append(SKTexture(imageNamed: "\(name)\(i)"))
    }

    textureDictionary["\(atlas):\(name)"] = textures

    return textures
}

So, the problem is that during first call fps drops significantly and CPU time increases, for example: move object to the left - from 30 fps it drops to 8 fps.

Taras Shchybovyk
  • 416
  • 4
  • 17
  • Where do you initialy preload textures ? – Whirlwind Apr 19 '16 at 10:14
  • in "init" method of derrived from SKScene class. Basically, animateMove method is a member of that class. – Taras Shchybovyk Apr 19 '16 at 10:26
  • Have you actually tried this : [preloadTextures: withCompletionHandler](https://developer.apple.com/library/mac/documentation/SpriteKit/Reference/SKTexture_Ref/#//apple_ref/occ/clm/SKTexture/preloadTextures:withCompletionHandler:) – Whirlwind Apr 19 '16 at 10:29
  • For some reason when I am using preloadTextures: withCompletionHandler program crashes, need to figure out why. But I tried another way, mentioned in the topic, call size method for each texture. Problem still exists. – Taras Shchybovyk Apr 19 '16 at 11:28
  • Is there some useful error message when app crashes? What you are passing to that method ? Also I linked a method from `SKTexture` class, but there is also a method from `SKTextureAtlas` class, called [preloadTextureAtlases: withCompletionHandler](https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKTextureAtlas/#//apple_ref/occ/clm/SKTextureAtlas/preloadTextureAtlases:withCompletionHandler:) None of these should crash if used correctly. – Whirlwind Apr 19 '16 at 11:52
  • *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection was mutated while being enumerated.' - the interesting thing collection is private and nobody have access to it. – Taras Shchybovyk Apr 19 '16 at 15:51
  • Same issue in this StackOverflow quesiton : http://stackoverflow.com/questions/22480962/nsgenericexception-reason-collection-nsconcretemaptable-xxx Do you get crash every time or randomly ? – Whirlwind Apr 19 '16 at 15:56
  • 1
    Look at this example and try it like that : http://stackoverflow.com/a/29421625/3402095 That would be one way (UI elements should be updated on main thread)... The other is to use `size` property, but you said that way didn't worked either. Personally, I can't reproduce what you are saying,so I can't comment more on this. Also I am not aware of your current setup, so it can happen that the error is on your side. As last resort, try to reproduce what you are saying in an empty project. Just use textures / atlas needed and see if you still getting that crash. If not,double check your code logic. – Whirlwind Apr 19 '16 at 16:12

1 Answers1

0

The problem was on my side in cacher, was:

let textureAtlas = SKTextureAtlas(named: atlas)
var textures = [SKTexture]()
for i in 0..<textureAtlas.textureNames.count {
    textures.append(SKTexture(imageNamed: "\(name)\(i)"))
}

now:

let textureAtlas = SKTextureAtlas(named: atlas)
var textures = [SKTexture]()
for i in 0..<textureAtlas.textureNames.count {
    let texture = textureAtlas.textureNamed("\(name)\(i)")
    texture.size()
    textures.append(texture)
}
Taras Shchybovyk
  • 416
  • 4
  • 17