我想在点击节点时发出声音。 目前的代码是:
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)
都没有用
最佳答案
为什么在按钮上运行声音操作不起作用?
这是来自文档:
An SKAction object is an action that is executed by a node in the scene (SKScene)...When the scene processes its nodes, actions associated with those nodes are evaluated.
表示节点的操作只有在节点被添加到场景中时才会运行。所以这没有效果:
playButton.runAction(sndButtonClick)
playButton.removeFromParent()
因为您已经从场景中删除了按钮,并且在应该执行操作时它不会出现在下一帧中。这就是 runAction
方法的工作原理:
Adds an action to the list of actions executed by the node...The new action is processed the next time the scene’s animation loop is processed.
另外,因为你是立即调用presentScene
无论如何不会有下一帧,所以即使你删除了removeFromParent
语句,声音也不会工作,因为没有下一帧。
为什么在场景中运行声音 Action 不起作用?
self.runAction(sndButtonClick)
将不起作用,因为您正在立即进行转换,而无需等待将执行排队操作的下一帧(如上所述)。
问题的解决方案
要在过渡前播放声音,您必须等待下一帧,您可以这样做:
runAction(sndButtonClick, completion: {
self.view?.presentScene(nextScene)
})
或
let block = SKAction.runBlock({
self.view?.presentScene(nextScene)
})
runAction(SKAction.sequence([sndButtonClick, block]))
防止泄漏:
考虑在 block 内使用捕获列表来捕获 self 以避免在需要时可能出现的强引用循环,如下所示:
let block = SKAction.runBlock({
[unowned self] in
//use self here
})
在您的这种特殊情况下,没有捕获列表应该是安全的,因为场景没有对 block 的强引用。只有block对场景有强引用,但是block执行后,因为没有东西保留它(没有强引用),所以会被释放,这样场景才能正确释放。但是,如果该 block 被声明为一个属性,或者执行该 block 的操作正在无限运行(使用 repeateActionForever
方法重复某个序列),那么您肯定会发生泄漏。
您应该始终覆盖场景的 deinit 以查看发生了什么(如果未调用它,则保留场景并导致泄漏)。
关于ios - 在 spritekit swift 中触摸节点时不播放声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35716994/