Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sprite Kit game "hickup" when the first sound is played

Tags:

sprite-kit

In my sprite kit game I use a SKAction to play a mp3 file when two sprites did collide. While the game works fine I noticed a small "hickup" in the game the first time the sound should be played. The complete game stops for about half a second. Afterwards everthing is fine and all following sounds work as they should. I noticed this behavoir in the simulator and on my iPhone 5s just the same.

What can I do to prevent this?

like image 602
TalkingCode Avatar asked Nov 18 '13 10:11

TalkingCode


3 Answers

You can preload a sound file by creating an SKAction to play it. (You don't need to run the action, so the sound won't actually play, but the file will be loaded.)

SKAction *preload = [SKAction playSoundFileNamed:@"my-sound-effect.caf" waitForCompletion:NO];

You don't have to save this instance for later re-use; any similarly-initialized SKAction will play instantly when run.

As a side note, and because I had a hard time finding this link, here's a link to a document containing Apple's "Best Practices for iOS Audio"; search "Best". It doesn't address preloading, but it does talk about formats, and suggests using uncompressed, IMA4, or AAC sound packaged in a CAF file. I thought of this because your example was playing an MP3, which may or may not end up using more CPU than you'd like at scale.

EDIT [Aug 2019, iOS12]:

I'm realizing now, five years later, that the “hiccup” is not due to file I/O on the sound file as I'd always assumed. I can use Instruments "System Usage" (on an iPhone 6 running iOS12.4) to prove that every SKAction playSoundFileNamed: will load the sound file from disk, even if it's already been played. However, it's only the first time that the main thread hangs briefly. Subsequent reads from disk, whether of that file or another sound file, are relatively quick.

I don't know what's causing the initial delay. But it's important to note you can trigger the "hiccup" by preloading or playing any sound effect. There is apparently no benefit from preloading all sound effects.

like image 192
Karl Voskuil Avatar answered Dec 02 '22 00:12

Karl Voskuil


I have a similar problem so here is what I found so far (I don't know if it fixes the problem because I can't try it right now).

I think the problem is that you didn't preload the sound effect. So when it plays for the first time, it is loaded and then played. That is why your game freezes.

The solution is to preload the effect when you initialize your scene. You can find an example in this tutorial (scroll down to the part named "Gratuitous Sound Effects"). It is pretty clear and well explained.

Hope it helps.

like image 45
Heyfara Avatar answered Dec 02 '22 00:12

Heyfara


To translate the Karl Voskuil preload sounds answer's in Swift 2.x :

let preloadSound = SKAction.playSoundFileNamed("my-sound-effect.caf", waitForCompletion: false)

so after you can do :

playSound(preloadSound)

...

func playSound(soundVariable : SKAction)
{
    runAction(soundVariable)   
}
like image 21
Alessandro Ornano Avatar answered Dec 02 '22 01:12

Alessandro Ornano