如何捕捉 SKScene 暂停或 audioEngine 停止的时刻?

Posted

技术标签:

【中文标题】如何捕捉 SKScene 暂停或 audioEngine 停止的时刻?【英文标题】:How can I catch moment SKScene became paused or audioEngine became stopped? 【发布时间】:2016-08-23 16:38:04 【问题描述】:

我有两个SKScene:GameScene 和EndScene,我在游戏过程中使用GameScene 的audioEngine 属性播放声音(该属性包含AVAudioEngine 对象)。游戏结束后,场景从 GameScene 变为 EndScene:

        self.view?.presentScene(EndScene())

之后,当用户点击«Restart»时,游戏重新开始,场景从EndScene变回GameScene:

        self.view?.presentScene(GameScene(), transition: SKTransition.crossFadeWithDuration(1.0))

当场景从 EndScene 切换到 GameScene 时,GameScene 会暂停一秒钟(因为参数值 SKTransition.crossFadeWithDuration(1.0))。由于 GameScene 被暂停,audioEngine 也被停止。在此之后,GameScene 会自动启动,但 audioEngine 不会启动并保持停止状态。然后,游戏在第一次尝试播放声音时崩溃,很明显:因为 audioEngine 已停止。 为了避免这种情况,我需要在它停止后启动audioEngine,但是在它发生的那一刻有一个问题要捕捉:我试图在GameScene的didMoveToView()中捕捉它,但是GameScene没有暂停,它后来暂停了,在 didMoveToView() 已经完成之后。 这是我的问题: 是否有适合这种情况的通知或事件处理程序?

【问题讨论】:

【参考方案1】:

最后,我放弃了寻找一些合适的通知或事件的尝试,并决定每次在声音播放之前检查 audioEngine 状态,在函数中播放声音。我认为这种方式相当有效:

func playSound(soundType: Sounds) 

    if !audioEngine.running 
        do 
            try audioEngine.start()
         catch 
        
    

    var soundNode = SKAudioNode()
    var waitingDuration = Double()

    switch soundType 
    case .enemyDestroyed:
        soundNode = SKAudioNode(fileNamed: "Blip001.wav")
        waitingDuration = 3
    case .playerDestroyed:
        soundNode = SKAudioNode(fileNamed: "Noise002.wav")
        waitingDuration = 5
    

    soundNode.autoplayLooped = false

    self.addChild(soundNode)
    soundNode.runAction(SKAction.changeVolumeTo(0.5, duration: 0))
    soundNode.runAction(SKAction.changeReverbTo(0.5, duration: 0))
    soundNode.runAction(SKAction.sequence([SKAction.play(), SKAction.waitForDuration(waitingDuration), SKAction.removeFromParent()]))


【讨论】:

【参考方案2】:

每次调用帧(每秒 60 次)时,使用 update 函数检查这一点。在其中放置一个条件语句(if、while 等)来检查您想要的条件。例如,使用它来检查场景是否暂停:

override func update(currentTime: CFTimeInterval) 

if isPaused == true 

// Code to run when scene is paused

       


请注意,这是在 Swift 3 和更低版本中,isPaused 只是 paused

另一种选择是使用像 whiledo-while 这样的循环来不断检查条件

【讨论】:

在问我的问题之前,我已经考虑过使用 update() 事件来捕捉这个,但在我看来这是一种相当粗糙的方式。使用 do-while 的方式(在 didMoveToView 结束时,正如我建议的那样)看起来更有效,感谢您的建议。但是,最后,我决定每次在播放声音之前检查 audioEngine 状态,在函数中播放声音。我认为这种方式相当有效。我已将其发布为下面我自己的问题的答案。

以上是关于如何捕捉 SKScene 暂停或 audioEngine 停止的时刻?的主要内容,如果未能解决你的问题,请参考以下文章

在SKScene暂停时动画SKSpriteNode的alpha

如何关闭 SKScene?

如何在 MyScene(SKScene 的子类)中打开 xib 或故事板窗口?

呈现 SKScene 后取消隐藏 UIButtons 时延迟?

向 SKSpriteNode(或 SKScene)添加背景模糊

在 Sprite Kit 中暂停 SKPhysicsWorld