Audio Source — Improving Immersion with Sound
Objective: Learn how to play sounds in Unity
Audio is so important in a game that we often take it for granted. While building this game I bet you noticed that something was missing. No sound!
No music, no laser or explosion sound effects are a huge turn off.
In this tutorial we are going to learn how to include sound in a game, how to play it via editor and, most importantly, via script.
Before starting, we have to know how Unity works in terms of sound. There are Audio Sources which are game objects component, carrying an Audio Clip and providing the possibility to play it and Audio Listeners. Actually there can be just one Audio Listener per scene.
Audio Listeners are component without any property by default attached to the camera, they act like a sort of microphone catching sound emitted by Audio Sources. If attached to a gameobject in a 3D scene (for example the player), the Audio Listener will simulate realistic sound effects based on Audio Source position and movement with respect to the listener. In 2D no effects are provided.
Our camera already as a listener and we are ok with that. Let’s start working with sounds. The easiest with we can do, as a start, is to add a background music. To do so we need an Audio Source component, we can add it to the camera itself.
In the Audio Clip property we can add our music file and click on Play on Wake: this property will allow to play the sound on start. Also loop is useful, since we need a constant music background. If you need, there are many other audio properties to tweak.
Now that we know of the existence of listeners and sources, we can easily tell which object has to hold sound, at least as a matter of coherence.
I just get a bunch of free sound from the asset store and imported them in my project. So let’s decide who plays what:
- Player is going to need a laser, a damage, a shield and an explosion sounds
- Power ups, collect and destruction sounds
- Enemy, collision and explosion sounds
- Asteroid, collision, laser and explosion sounds.
Each sound will have its Audio Source component on the corresponding object. I know there are many duplicates but there is a reason: in the future I may want to have different explosion sounds and in this way I already have separated components and logics.
Let’s add the component and the clips to each object and deselect Loop and Play on Wake options.
Now we want play the sounds in a specific moment.
Let’s take as example the Player sounds. In the Player script we have to grab reference to the sources at the start, but I want to improve code clarity through a few more lines.
The GetComponents method will return an array of AudioSource, sorted as you find in the Inspector. So, you’ll have to remember elements 0–3 to which clips correspond.
To avoid confusion in future reading (“what the hell is this _sources.Play() ??”) I ‘m going to use a dictionary. Dictionaries are key-value maps in which to each key, of a certain type, corresponds a unique value, of a certain type. Dictionaries are accessible through a comfortable array notation. I chose a <string, AudioSource> dictionary, so I can link each sound to a word, as you can see in the initialization lines.
Now let’s say we want to play the laser sound. Where should we do it? of course in the shooting method, typically after the instantiation of the prefab (easy to remember: light faster than sound).
Something like that. Let’s look at the damage part:
And so on for other sources and objects.
Don’t forget sounds and music in the Main Menu Scene!
Audio Bug Fix
You may notice a little bug: when collecting a power up no sound is played!
This is because, the collision logic will destroy the power up right after playing the sound and giving power to the player. This will result in an instant audio kill! To solve this, a little delay should be put in destroying the powerup, but before destruction it still has to disappear and avoid interactions.