在 spritekit swift 中触摸节点时没有播放声音

Posted

技术标签:

【中文标题】在 spritekit swift 中触摸节点时没有播放声音【英文标题】:sound is not playing when node is touched in spritekit swift 【发布时间】:2016-03-01 07:27:07 【问题描述】:

我想在单击节点时发出声音。 目前的代码是:

    let sndButtonClick = SKAction.playSoundFileNamed("button_click.wav", waitForCompletion: false)

从接触开始

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 


    for touches: AnyObject in touches 


        let location = touches.locationInNode(self)
        if playButton.containsPoint(location) 
           playButton.runAction(sndButtonClick)
            playButton.removeFromParent()

            let nextScene = GamePlayMode(size: self.scene!.size)
            nextScene.scaleMode = self.scaleMode
            self.view?.presentScene(nextScene)
        

我对游戏模式中两个节点的碰撞做了完全相同的事情,它可以工作,但在主菜单中它不起作用!

我试过了

self.runAction(sndButtonClick)

然后

playbutton.runAction(sndButtonClick)

两个都没用

【问题讨论】:

我怀疑你的问题出在下一行; playButton.removeFromParent。这将删除节点并取消其操作。作为一个实验,将剧本的waitForCompletion 更改为true @PriceRingo waitForCompletion 参数意味着动作的持续时间将与音频播放的长度相同,但由于runAction 方法的工作原理,动作仍不会执行。我在回答中描述了这一点。 【参考方案1】:

为什么在按钮上运行声音操作不起作用?

这是来自文档:

SKAction 对象是由节点执行的动作 场景 (SKScene)...当场景处理其节点时,会评估与这些节点关联的操作。

表示节点的动作只有在节点被添加到场景时才会运行。所以这没有效果:

playButton.runAction(sndButtonClick)
playButton.removeFromParent()

因为您已经从场景中移除了按钮,并且在应该执行操作时它不会出现在下一帧中。这就是runAction 方法的工作原理:

将一个动作添加到节点执行的动作列表中...在下一次处理场景的动画循环时处理新动作。

另外,因为你立即调用presentScene,所以无论如何都不会有下一帧,所以即使你删除removeFromParent语句,声音也不会起作用,因为没有下一帧。

为什么在场景中运行声音动作不起作用?

self.runAction(sndButtonClick) 将不起作用,因为您正在立即进行转换,而无需等待将执行排队操作的下一帧(如上所述)。

问题的解决方案

要在过渡前播放声音,您必须等待下一帧,您可以执行以下操作:

runAction(sndButtonClick, completion: 
   self.view?.presentScene(nextScene)
)

let block = SKAction.runBlock(
   self.view?.presentScene(nextScene)
)

runAction(SKAction.sequence([sndButtonClick, block]))

防止泄漏:

考虑在块内使用捕获列表来捕获自身,以避免在需要时可能出现强引用循环,如下所示:

let block = SKAction.runBlock(
   [unowned self] in
   //use self here
)

在您的这种特殊情况下,没有捕获列表应该是安全的,因为场景没有对块的强引用。只有block对场景有强引用,但是block执行后,因为没有保留它(没有强引用),所以会被释放,从而可以正确释放场景。但是,如果块被声明为属性,或者执行块的操作无限运行(使用repeateActionForever 方法重复某个序列),那么您肯定会有泄漏。

您应该始终覆盖场景的 deinit 以查看发生了什么(如果未调用它,则会保留场景并导致泄漏)。

【讨论】:

非常感谢您提供的信息丰富的回答!问题解决了! @prival 没问题 :) 很高兴为您提供帮助。另外,如果您有一个带有过渡的场景,该过渡在实际过渡发生之前有延迟,例如。 view?.presentScene(nextScene, transition: SKTransition.fadeWithDuration(someDuration)),声音也可以。当然,只要您在场景本身或添加到场景中的节点上运行声音动作。

以上是关于在 spritekit swift 中触摸节点时没有播放声音的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit + Swift - 如何通过缓动移动节点?

(Swift + Spritekit) - 完全删除节点及其数据

touchesBegan Swift 2 自定义 SpriteKit 节点

使用 Swift + SpriteKit 将节点移动到手指

(Swift SpriteKit) 沿触摸方向旋转精灵

在Sprite纹理中检测触摸而不是整个框架iOS Swift SpriteKit?