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

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.


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.


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

Tags:

Sprite Kit