2016-03-01 48 views
1

点击节点时我想要发出声音。 目前的代码是:在spritekit swift中点击节点时声音不会播放

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) 
     } 
} 

我做同样的事情在gameplaymode两个节点的碰撞和它的作品,但在主菜单中这是行不通的!

我试图

self.runAction(sndButtonClick) 

然后

playbutton.runAction(sndButtonClick) 

既没有工作

+1

我怀疑你的问题是在下一行; 'playButton.removeFromParent'。这将删除该节点并取消其操作。当一个实验改变剧本的'waitForCompletion'为'true'。 –

+0

@PriceRingo waitForCompletion参数意味着动作的持续时间将与音频播放的长度相同,但仍然不会因为runAction方法的作用而执行动作。我在我的回答中描述了这一点。 – Whirlwind

回答

3

为什么运行上的按钮声音动作不起作用?

这是从文档:与相关联的

一个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 
}) 

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

你应该总是重写场景的deinit以查看发生了什么(如果它没有被调用,保留场景并导致泄漏)。

+0

非常感谢您提供丰富的答案!问题解决了! – prival

+1

@prival没问题:)很高兴帮助。作为补充,如果你有一个场景的转场在实际转场发生之前有延迟,例如。 'view?.presentScene(nextScene,transition:SKTransition.fadeWithDuration(someDuration))',声音也会起作用。当然,只要你在场景本身或者添加到场景的节点上运行声音动作。 – Whirlwind