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:
GameScene
property isPaused
to true
.GameViewController
, setting the pausesOutgoingScene
and pausesIncomingScene
properties of SKTransition
when presenting GameScene
/MenuScene
.timerNode
to add as a child to the scene, then saying timerNode.run
and setting its isPaused
property..speed
instead of .isPaused
.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.
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.