在 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) - 完全删除节点及其数据