Playing sounds in SpriteKit using SKAction
This article discusses adding sound effects to a Sprite Kit project using SKAction
and provides you with a couple of tips and tricks and useful code snippets. It also explains performance issues that may appear when dealing with sounds not in the best, most efficient way and gives insights into how to avoid these problems.
Using SKAction
There are many ways you can play sounds in Sprite Kit game. The easiest way of playing a sound file is using a SKAction
. It has a built-in method for handling audio playback.
1
2
+ (SKAction *)playSoundFileNamed:(NSString*)soundFile
waitForCompletion:(BOOL)wait;
The method simply creates an action that plays a sound. Sound file name must be the name or path of a file of a platform supported audio file format. Apple recommends using a LinearPCM
format audio file with 8 or 16 bits per channel for best performance. After creating the action one has to run it to hear the effect.
1
2
[[self scene] runAction:[SKAction playSoundFileNamed:@"sound.caf"
waitForCompletion:NO]];
iOS and macOS have a native audio file format, the Core Audio Format (or CAF
) file format. CAF
should be your first choice format. However, you can also use other formats like AIFF
, WAV
or even MP3
. Full list of supported audio file formats on macOS and iOS can be found here (iOS) and here (OS X). Keep in mind that for very short sound files, say shorter than 4 seconds, MP3
isn’t ideal since MP3
file is buffered into a 250KB
buffer. Try CAF
or WAV
instead.
When using SKAction
‘s playSoundFileNamed:
method one has to remember to cache the action if it’s executed many times. Not doing this might result in a nasty ‘Failed to Load Resource’
crash when the sound file is being loaded simultaneously by many SKAction
instances.
Terminating app due to uncaught exception ‘Failed to Load Resource’, reason: ‘Resource sound.wav can not be loaded’
Moreover, for performance reasons, unnecessary disk operations should be avoided. So we should create a SKAction
that represents playing the sound, and reuse that object so the audio file is only loaded once. Thus, the best way of doing this is to store the repeated action in a static variable. The following sample code shows a good example of how to do it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static SKAction *sharedMissileLaunchSoundAction = nil;
- (SKAction *)missileSoundAction {
return sharedMissileLaunchSoundAction;
}
+ (void)loadSharedAssets {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMissileLaunchSoundAction = [SKAction playSoundFileNamed:@"missile.caf"
waitForCompletion:NO];
});
}
Drawbacks of SKAction approach
Playing sounds using SKAction
is very simple and straightforward. However there is no way you can configure the way the sound is played. The biggest drawback is that there is no way of controlling the volume of the sound played using the playSoundFileNamed:
method. If you need more flexibility in playing the sounds you might consider using [
AVAudioPlayer`](https://developer.apple.com/documentation/avfoundation/avaudioplayer).
However, for simple games that do not require sophisticated audio engines, using SKAction
to play sound is the best and the fastest way.