Search code examples
iossprite-kitskactioncompletionhandler

SKAction.run not working until program execution paused/resumed


First time using SpriteKit - tapping a start button calls startLevel method in GameScene that has a player sprite fire two SKAction.run statements in a SKAction.sequence. The startLevel method has a completion block that triggers a message to the console and updates game state.

Tapping start displays the message, but the SKAction.run statements don't work unless I first pause program execution, and then click resume before tapping the start button. If I stop the level and tap a retry button, the same startLevel method is called, and it works fine without pausing execution.

Here's the method (player, marker, and door, are all optional objects that store their sprites; when tapping start, I verified that none of the sprites are nil, none of them are paused, and GameScene and SKView are not paused):

func startLevel(finished: () -> ()) {
    guard let player = player,
        let marker = marker,
        let door = door else {
        fatalError()
    }
    player.sprite.run(SKAction.sequence([
        SKAction.run({ marker.pop(appear: true) }),
        SKAction.run({ door.slide(open: true) }),
    ]))
    finished()
}

Here's the GameScene code that calls startLevel:

startLevel(finished: { () -> () in
    print("ALERT: startLevel finished")
    levelStarted = true
})

I tried adding a run method completion block with a console message, and the message never prints. It seems that the player.sprite.run method is simply ignored (unless I pause execution first), and I don't understand why. Thanks for your help.

BTW - all the code above is outside GameScene’s update method, and the marker and door methods above are both used in didBegin() and didEnd(), and they work fine there.


Solution

  • In iOS 11 Apple made Spritekit Scenes and objects paused by default.

    What I do to combat this is...

    in my SKScene

    override func didMove(to view: SKView) {
    
        //this ensures that the scene is not paused
        self.isPaused = false
    }
    

    and in each of my custom objects setup or init

    self.isPaused = false