0

I am learning SceneKit, and have a the following code that plays a sound when my ball hits a wall.

if contactNode.physicsBody?.categoryBitMask == CategoryWall {

        let hitSound = sounds["bump"]!
        ballNode.runAction(SCNAction.playAudio(hitSound, waitForCompletion: true))
        }

This works, however I only wish to play the sound when the ball initially hits the wall, currently it is rolling along a wall, and this causes the sound to try and repeat and therefore causes problems.

I tried altering the waitForCompletion to false or true, this didn't help.

Is there a method or attribute that can be set to check for initial contact and then once contact is broken reset?

thanks in advance.

Kev

Lynxbci
  • 71
  • 7

2 Answers2

0

I am facing this problem in lot of my apps aswell and the only working solution I found until now is using variable to create some delay between touches. For example:

var touched = false

func physicsWorld(){
touched = true
if !touched{
   let hitSound = sounds["bump"]!
      ballNode.runAction(SCNAction.playAudio(hitSound, waitForCompletion: true))
   }
   DispatchQueue.main.asyncAfter(deadline: .now() + 0.1){
      touched = false
   }
}

} 

Yeah it is a terrible solution, but in case of no better solution it works.

Jakub
  • 11
  • 6
0

I solved this by ensuring that the impact audio is only played on contact and to completion by setting a unique key for the sound action. This ensures there aren't multiple sound actions being added to the node in rapid succession (typically seen at low impact angles):

  func playSound(node:SCNNode, name:String) {
     //Where [sounds] are pre-loaded SFX
     let sound = sounds[name]
     if (node.action(forKey: "playSFX") != nil) {
       return
     }
     let action = SCNAction.playAudio(sound!, waitForCompletion: true)
     node.runAction(action, forKey: "playSFX")
   }
rswayz
  • 1,122
  • 2
  • 10
  • 21