iosswiftsprite-kitskaction

How to pause a timer run through SKAction in SpriteKit


In my game built on SpriteKit the player has a set amount of time to complete each level, and on expiration either a game over method or a next level one is called.

Since I know that using NSTimer combined with SpriteKit is bad under different points of view, what I did in my GameScene is building the timer as a sequence of SKActions like this:

    private func runTimer(duration: TimeInterval) {
       let wait = SKAction.wait(forDuration: duration)
       let endLevel = SKAction.run { [weak self] in
          self?.handleEndLevel()
       }
       run(SKAction.sequence([wait, endLevel]), withKey: "timer")
}

Since I also have a pause button, which presents a MenuScene, and a resume button, what I'm trying to achieve is to pause/unpause the timer. What is the proper way to achieve this?

Here's what I already tried with no luck:

All of these lead to the same result: even if the game is paused and resumed, the timer runs as it was never paused, so ending the level before it is supposed to. Since I'm still learning SpriteKit, my understanding of the isPaused property is that it is used to determine wheter actions are performed, so I thought an already running action would be paused, this might be wrong on my part maybe tho.

I know there might be a drastic solution: I can call removeAction(forKey: "timer") on pause while storing the time at which it was removed, and with some calculation I can set up another timer with the amount of time left once the game is resumed. This looks not pretty and overcomplicated tho and I can't believe Apple did not implement something easier.


Solution

  • After a debug, I found out that the issue lies in the fact that when the user taps the pause button I'm presenting another scene and I'm setting gameScene.isPaused to true in the ViewController. If I set the isPaused property in the GameScene, without presenting other scenes, the scene actually pauses. The reason of this behaviour is still unclear to me.

    An important note, SKAudioNodes must be paused and resumed separately using SKAction.pause, otherwise the background music will pause but on resume there will be a (small) offset between the audio player state and the scene state.