如何暂停/恢复SpriteKit中通过SKAction实现的计时器
解决SpriteKit中SKAction计时器的暂停/恢复问题
核心思路
用SKAction实现的计时器,单纯依靠isPaused、speed或场景切换属性无法有效暂停的核心原因是:SKAction的计时进度绑定到节点/场景的运行周期,但场景切换或全局暂停可能无法精准中断已启动的wait动作的内部计时。最简便的可靠方案是手动记录剩余时间,暂停时终止当前计时动作,恢复时基于剩余时间重新启动。
具体实现步骤
- 添加属性存储计时状态
在GameScene中定义两个属性,用于跟踪剩余时间和当前计时动作:
class GameScene: SKScene { // 剩余关卡时间(可根据需求设置初始值) var remainingTime: TimeInterval = 60.0 // 标记计时动作的key,方便后续精准移除 private var timerActionKey = "levelTimer" }
- 封装计时器启动方法
写一个通用的启动计时器方法,基于当前remainingTime创建动作序列:
func startTimer() { // 创建计时动作:等待剩余时间后触发超时逻辑 let timerSequence = SKAction.sequence([ SKAction.wait(forDuration: remainingTime), SKAction.run { [weak self] in self?.handleTimeOut() // 你的超时处理逻辑:游戏结束/进入下一关 } ]) // 用key标记动作,方便后续精准移除 run(timerSequence, withKey: timerActionKey) }
在场景初始化(比如didMove(to:))时调用startTimer()启动计时。
- 暂停计时器与切换菜单
点击暂停按钮时,计算已流逝的时间、更新剩余时间,然后终止当前计时动作,再切换到MenuScene:
func pauseGame() { // 获取当前运行的计时动作 guard let runningAction = action(forKey: timerActionKey) else { return } // 计算已流逝的时间:总时长 - 剩余时长(考虑speed影响) let elapsedTime = runningAction.duration - (runningAction.speed * runningAction.timeRemaining) remainingTime -= elapsedTime // 终止当前计时动作 removeAction(forKey: timerActionKey) // 切换到MenuScene,传递剩余时间给菜单场景,方便恢复时使用 let menuScene = MenuScene(size: size) menuScene.savedRemainingTime = remainingTime let transition = SKTransition.fade(withDuration: 0.3) transition.pausesOutgoingScene = false // 已手动终止计时器,无需系统暂停 view?.presentScene(menuScene, transition: transition) }
- 从菜单恢复游戏
在MenuScene中添加恢复按钮的点击逻辑,传递保存的剩余时间回GameScene并重启计时器:
class MenuScene: SKScene { // 存储从GameScene传递来的剩余时间 var savedRemainingTime: TimeInterval = 0.0 func resumeGame() { let gameScene = GameScene(size: size) gameScene.remainingTime = savedRemainingTime let transition = SKTransition.fade(withDuration: 0.3) transition.pausesIncomingScene = false view?.presentScene(gameScene, transition: transition) } }
如果是复用原GameScene实例(而非重新创建),只需回到场景后直接调用startTimer()即可。
为什么之前的方法无效?
- 设置
GameScene.isPaused = true:场景暂停后,若后续切换到MenuScene,原场景可能被系统释放或脱离运行周期,计时动作的暂停状态无法维持。 - 调整
SKTransition的暂停属性:仅控制场景切换过程中的暂停,无法影响已启动的SKAction的计时进度。 - 设置节点
isPaused或speed:若计时动作绑定的节点未被正确暂停(或被其他逻辑修改),则计时仍会继续。
内容的提问来源于stack exchange,提问作者oneshot
相关产品推荐
相关产品推荐

