sound is not playing when node is touched in spritekit swift

谁说我不能喝 提交于 2019-12-08 04:44:32

问题


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!

I tried

self.runAction(sndButtonClick)

then

playbutton.runAction(sndButtonClick)

both didnt work


回答1:


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.

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:

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.

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

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:

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.

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



来源:https://stackoverflow.com/questions/35716994/sound-is-not-playing-when-node-is-touched-in-spritekit-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!