Space Short Monthly: Music and SFX
The surprising time sink
No space shooter game is complete without some background music and explosion sounds. Adding background music and sound effects (SFX) to the game was actually pretty easy, barring some pitfalls with pooling which I’ll detail below.
The most time-consuming part wasn’t adding the music and effects; it was choosing them. I could spend hours listening to various tracks, explosions and power up sounds. But I want to release this game sometime, y’know?
I chose them in the end, but I’ll probably change my mind 😆
This article is in 3 parts:
- Great places to find free music and SFX for commercial use. But be warned! This takes time.
- How to add them to your game
- How to add SFX to a pooled object
Free music and SFX
I used two great sites:
FreeSound:
There are tons of sounds, all Creative Commons 0 licensed. In other words, completely free. I am keeping a list of all I’m using (which will probably change 🙄) and I plan to attribute in the “About” page, because they deserve it.
In FreeSound, you can create a free account and bookmark all the sounds that you are interested in, creating different lists if you wish. You can download as much as you want, and the sounds are mostly .wav files.
Pixabay:
I use Pixabay extensively for free images and videos, and they have tons of SFX and music clips as well:
In Pixabay, you can also bookmark the sounds and put them in different collections.
Pixabay vs FreeSound
In Pixabay bookmarking is two clicks (expand and click) vs FreeSound where it’s just one (the book logo on the right). In Pixabay there is less choice (488 Explosion
vs 2914 in FreeSound) which actually makes searching harder, as many keywords to narrow down the search simply don’t work, whereas in FreeSound also searching for Space Explosion
or Space arcade
returns many results. Also, in FreeSound you can filter results by length, which is extremely useful.
Trimming your clip
If you’ve found the perfect sound, but it has a second of silence at the end, you need to trim it. Unity Audio sources cannot play more than one clip at once, so if you’re shooting a lot of lasers, you need the SFX of one to end before the next laser is shot. There are many options for this; I used mp3cut, which allows you to trim a file online, very simply.
Code
You’ve found your music and SFX? (Out of curiosity, how long did it take you? Let me know in the comments.) Let’s add them to the game!
As always, a great source for code with step by step explanations is Create with Code.
Background music
I wanted two different types of music — the general background music, and a spookier track for the boss levels. So I can’t just add an Audio Source with a clip to the camera, as stated in the tutorial. I added it to the camera, and then activated it from my LevelManager
(or GameController
, or whatever script knows which level you’re on). Like this:
- Go to
Main Camera
. Add anAudio Source
component by clickingAdd Component
. Leave theAudioClip
andOutput
empty.
2. In your Controller script, add the following:
public class LevelManager : MonoBehaviour
{
[SerializeField] AudioClip mainMusic;
[SerializeField] AudioClip bossMusic;
AudioSource audioSource;
void Start()
{
//Get audio source
audioSource = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>().GetComponent<AudioSource>();
//set the main music and play it in a loop
audioSource.clip = mainMusic;
audioSource.loop = true;
audioSource.Play();
}
void updateLevel(int level) // or whatever your level update is called
{
if (level <= 4)
{
//do nothing music-wise, our music is already working
}
else if (level == 5) //first boss
{
audioSource.clip = bossMusic;
audioSource.Play();
}
else if (level < 10)
{
if (level == 6) //back to main music
{
audioSource.clip = mainMusic;
audioSource.Play();
}
}
else if (level == 10) //second boss
{
audioSource.clip = bossMusic;
audioSource.Play();
}
else //game over - put your `you won` or `you lose` music here,
//or just put the main music back
{
audioSource.clip = mainMusic;
audioSource.Play();
}
}
For more readable code, you can create a function:
void playClip(AudioClip clip)
{
audioSource.clip = clip;
audioSource.Play();
}
void updateLevel(int level) // or whatever your level update is called
{
if (level <= 4)
{
//do nothing music-wise, our music is already working
}
else if (level == 5) //first boss
{
playClip(bossMusic);
}
else if (level < 10)
{
if (level == 6) //back to main music
{
playClip(mainMusic);
}
}
else if (level == 10) //second boss
{
playClip(bossMusic);
}
else //game over - put your `you won` or `you lose` music here,
//or just put the main music back
{
playClip(mainMusic);
}
}
And you’re done :) Pretty easy, right?
Sound effects
Here I added audio sources to the GameObject creating them. So to add the sound of the shooting laser, add an Audio Source to yourPlayer
object, in exactly the same way as in the previous section. Then in the Player
script, add the following code:
public class PlayerController : MonoBehaviour
{
//SFX
public AudioClip laserSound;
private AudioSource playerAudio;
void Start()
{
playerAudio = GetComponent<AudioSource>();
}
public void OnShoot()
{
//instantiate laser type
if (hasPowerup) //different laser color
{
GameObject laser = gameManager.playerPowerupLaserPool.Get();
laser.transform.position = transform.position;
}
else
{ //regular laser color
GameObject laser = gameManager.playerLaserPool.Get();
laser.transform.position = transform.position;
}
// play sound
// note the 1.0f, this is the volume. In the future I will get this from settings
playerAudio.PlayOneShot(laserSound, 1.0f);
}
}
And that is done as well :) Don’t forget to drag the clip to the script.
SFX and pooling
I created a lovely explosion particle effect. To make it sound explosion-y, add an Audio Source to it, same as before. However, this time drag your explosion clip to it, as we have no intention of changing it (in the Player, it will have some other effects as well, e.g. power-up sounds. So the clip is changed programmatically there).
I have an ExplosionManager
that returns the explosion to the pool when done, using the OnParticleSystemStopped
function. But I couldn’t find an OnParticleSystemStarted
function, or anything like it. I also tried using OnEnable
, but apparently deactivating an Audio Source and activating it again mixes it up somehow — I couldn’t get it to play twice. If anyone got this to work through OnEnable
or similar function, please write below.
So instead, change the Pool actionOnGet
function
explosionPool = new ObjectPool<ParticleSystem>(
createFunc: () => Instantiate(explosionEffect),
actionOnGet: (obj) => {
obj.Play();
obj.GetComponent<AudioSource>().Play(); //<-- this
},
actionOnRelease: null,
actionOnDestroy: (obj) => Destroy(obj),
defaultCapacity: 30,
collectionCheck: true, maxSize: 100);
So in addition to playing the effect itself, it also plays its sound effect.
Would love to hear your comments below :)