简体   繁体   English

在spritekit swift中触摸节点时,声音不播放

[英]sound is not playing when node is touched in spritekit swift

I want to have a sound when a node is clicked. 我希望在点击节点时发出声音。 currently the code is: 目前的代码是:

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

and from touches began its 并从接触开始

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

I did the exact same thing for the collision of two nodes in gameplaymode and it works but in main menu it does not work! 我为gameplaymode中的两个节点的碰撞做了完全相同的事情,它可以工作,但在主菜单中它不起作用!

I tried 我试过了

self.runAction(sndButtonClick)

then 然后

playbutton.runAction(sndButtonClick)

both didnt work 两者都没有用

Why running sound action on a button doesn't work ? 为什么在按钮上运行声音操作不起作用?

This is from the docs: 这是来自文档:

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. SKAction对象是由场景中的节点(SKScene)执行的动作......当场景处理其节点时,将评估与这些节点关联的动作。

Means the actions for a node will run only if the node is added to the scene . 表示仅当节点添加到场景时,节点的操作才会运行。 So this has no effect : 所以这没有效果:

playButton.runAction(sndButtonClick)
playButton.removeFromParent()

because you have removed the button from the scene and it will not be present in the next frame when actions should be executed. 因为您已从场景中删除了该按钮,并且在执行操作时它不会出现在下一帧中。 That is how runAction method works: 这就是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. 将操作添加到节点执行的操作列表...下次处理场景的动画循环时将处理新操作。

Also, because you are immediately calling presentScene there will be no next frame anyways, so even if you delete removeFromParent statement, sound will not work, because there is no next frame. 另外,因为你正在立即调用presentScene所以不会有下一帧,所以即使你删除removeFromParent语句,声音也不会起作用,因为没有下一帧。

Why running sound action on a scene doesn't work? 为什么在场景上运行声音动作不起作用?

self.runAction(sndButtonClick) won't work because you are making a transition immediately without waiting for a next frame where the queued actions will be executed (like described above). self.runAction(sndButtonClick)将无法正常工作,因为您无需等待执行排队操作的下一帧(如上所述)即可立即进行转换。

Solution for the Problem 解决问题的方法

To play the sound before transition, you have to wait for a next frame, and you can do something like: 要在转换前播放声音,您必须等待下一帧,并且您可以执行以下操作:

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

or 要么

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

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

Preventing Leaks: 防止泄漏:

Consider using capture list inside of a block which captures self to avoid possible strong reference cycles when needed, like this: 考虑在块中使用捕获列表捕获self以避免在需要时可能的强引用周期,如下所示:

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

In this particular case of yours, it should be safe to go without capture list because scene doesn't have a strong reference to the block. 在你的这种特殊情况下,没有捕获列表应该是安全的,因为场景没有对块的强引用。 Only block has strong reference to the scene, but after the block is executed, because nothing retains it (no strong references to it), it will be released, thus the scene can be released correctly. 只有块具有对场景的强引用,但是在块执行后,因为没有任何东西保留它(没有强引用),它将被释放,因此场景可以正确释放。 But, if the block was declared as a property, or the action which executes the block was running infinitely (using repeateActionForever method to repeat a certain sequence), then you will have a leak for sure. 但是,如果块被声明为属性,或者执行块的操作无限运行(使用repeateActionForever方法重复某个序列),那么肯定会有泄漏。

You should always override scene's deinit to see what is going on (if it is not called, something retaining the scene and causing the leak). 你应该总是覆盖场景的deinit来看看发生了什么(如果它没有被调用,某些东西会保留场景并导致泄漏)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM