我希望在点击节点时发出声音。 目前的代码是:
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)
我为gameplaymode中的两个节点的碰撞做了完全相同的事情并且它可以工作但是在主菜单中它不起作用!
我试过
playbutton.runAction(sndButtonClick)
然后
{{1}}
都没有工作
答案 0 :(得分:3)
为什么在按钮上运行声音操作不起作用?
这是来自文档:
SKAction对象是由节点中的节点执行的操作 scene(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]))
防止泄漏:
考虑在块内部使用捕获列表捕获self以避免在需要时可能的强引用周期,如下所示:
let block = SKAction.runBlock({
[unowned self] in
//use self here
})
在你的这种特殊情况下,没有捕获列表应该是安全的,因为场景没有对块的强引用。只有块具有对场景的强引用,但是在块执行后,因为没有任何东西保留它(没有强引用),它将被释放,因此场景可以正确释放。但是,如果块被声明为属性,或者执行块的操作无限运行(使用repeateActionForever
方法重复某个序列),那么您肯定会有泄漏。
你应该总是覆盖场景的deinit来看看发生了什么(如果它没有被调用,某些东西会保留场景并导致泄漏)。