In this article, we are going to cover how to create an Audio Manager that will handle all the sounds in the game, be called accessed from all game objects and move from scene to scene.
This script is uses the Brackey’s script. I wrote this to make sense of it in my own head and hopefully add some insight for others*
Create an empty game object, create a new script called “Audio Manager”.
We are going to create a public class that will also use the Audio library (“UnityEngine.Audio). We make this a custom class by removing the Monobehavior and this script is NOT attached to a game object.
This class will require an Audio Clip “clip”. In the Audio manager, this will allow us to assign an audio clip to it. Next, we can add properties of an audio clip we will want to be able to adjust like volume. In order for these variables to show up in the inspector, we need to serialize them using [System.Serializable].
In the Audio Manager script (DO NOT forget to use UnityEngine.Audio library just like the Sound Class script), we are going to create an array type Sound called “sounds”.
Since we serialized the Sound Class, we can go to the inspector and we can add elements to the array and populate it with Sound Clips.
We are going to add a string variable to the Sound Class, so we can give each audio clip in the array a name. This will allow use to search the audio clips by name and play the correct one using the Audio Manager.
Going a step further we can give the float variables (volume, pitch) a slider so they audio properties can be adjusted in the inspector.
We can see in the inspector, we can give the Audio Clip a name and adjust those audio properties using a slider.
For audio clips to play, an Audio Source needs to be added to the clip. The Audio Manager is going to handle all of the audio for the game, so we want the script to be able to handles every time we add to the Audio Clip array in the inspector.
We are going to assign the Audio Sources to all of the Audio Clips in the array on Awake. Awake method loads before the Start method and we need the audio sources to be attached before we can play any sounds in the Start.
In attaching the Audio Source to each Audio Clip, we are going to use a foreach loop which will loop through each element of an array. “s” is a global variable that will represent each element in the array of sounds.
In the Sound Class, we will need to add an AudioSource type variable and make it public. Since it is public, it will appear in the inspector, but we want to keep it hidden so we can use [HideInInspector] to keep this public variable off the inspector.
Back in the Audio Manager, we can store the AudioSource component in the variable “s”.
Once the AudioSource component is attached, we can assign each of the Sound Class variables to each AudioClip in the sounds array.
In the inspector, when the game is played the clip, volume and pitch assigned to the element in the sounds array is copied over to the AudioSource.
Since we have the AudioClip list setup, we want to be able to search and play an AudioClip from this list.
We create a public method on the Audio Manager script and require a string parameter “targetname”.
We use a foreach loop to go through each audio clip “item” in the sounds array and check to see if the current element or “item” name in the array is equal to the “targetname” passed in the parameter. When this is true we use the Play method using the audio source.
In Start, we can call the Play method we made and pass in the name (the name we gave the clip in the inspector) of the Audio Clip we want to play. In the example above, we want to play the theme music or background music when the Audio Manager script starts. The clip will play once, which isn’t a problem for most sounds but we want it to be looping since it is in the background.
So, we need to add a loop variable to the Sound Class.
In the Audio Manager, we need to set the loop property on the audio source to the value of the loop variable assigned in the inspector.
In the inspector, we can now determine if we want the clip to Loop or not.
We are going to make this Audio Manager game object a prefab. This will allow it to be moved to different scenes. You can use an Audio Manager for each scene since the game objects are destroyed from scene to scene. But, for this example, we will have one Audio Manager for the entire game.
This means we need to keep the Audio Manager from not being destroyed from scene to scene, so we will add a DontDestroyOnLoad and pass in the game object in the Awake.
This prevents the Audio Manager from being destroyed from scene to scene, but if you have an Audio Manager in each scene this will mean you will end up with multiple Audio Managers as you progress through the scenes since they are not being destroyed.
To prevent having multiple Audio Managers we will create an instance. On Awake, we check to see if there isn’t already an instance of the Audio Manger and if there isn’t we assign the instance to this.
If there is already an instance of Audio Manager, we destroy the game object and return to prevent any additional code from running
Now, we have a Singleton Audio Manager that play an audio clip we want by passing in the name we give it.
The example above shows how to access the Play method we created using the Audio Manager instance and pass in the Audio Clip name we want to play. In this case it is the play jump sound when the player jumps by pressing the space bar.