Unity3D: How to Play Sound FX!
Would you like to know how to play sound fx for your games in Unity? You’ve come to the right place!
The objective is to create a modular sound system to call a specific sound clip to their respective place in code. If you know about the SOLID Principles in software engineering, then you should remember the ‘S’ in Solid.
Single Responsibility Principle.
We want to create an object that will be responsible for the audio of the game. Then we can use it as a reference for other scripts to communicate too.
Creating the Game Object
First, let's create an empty game object and name it “Audio_Manager.”
This will hold the data for all of our sound clips.
We also want to attach the “Audio Source” component. We will reference it later to play any sound that is called.
Creating the Script
We need to create a script and call it “AudioManager.” Attach it to the “Audio_Manager” game object.
Open the script so we can start programming.
Adding Code
Get rid of the start and update functions. We won’t be using them. You should have a nice clean interface (class layout) now.
using UnityEngine;public class AudioManager : MonoBehaviour
{
}
We need a reference to the audio source attached to the “Audio_Manager” game object.
[SerializeField] private AudioSource _audioSource = null;
Save the script, head back to Unity, and attach the audio source component to the new field in the inspector.
We also want to create variables of type “AudioClip” to store our sound clips.
[SerializeField] private AudioClip _laser = null;
[SerializeField] private AudioClip _explosion = null;
[SerializeField] private AudioClip _powerup = null;
Now that we have our Audio Source and Audio Clips, we can create specific public methods for each sound clip. It will allow other scripts to call them, and that is what we want to do.
public void PlayExplosionSound()
{
_audioSource.PlayOneShot(_explosion);
}public void PlayLaserSound()
{
_audioSource.PlayOneShot(_laser);
}public void PlayPowerupSound()
{
_audioSource.clip = _powerup;
_audioSource.Play();
}
We need to grab our _audioSource
component to access the PlayOneShot(audio clip here)
function. We then need to pass in the specific audio clip into the argument of the function.
What is PlayOneShot()
? It does not cancel clips that are already being played. So if we have multiple explosions at once, the previous sound clip won’t cut off. It will prevent it so.
This part is done! I am only calling three methods that have references to playing their respective audio clips. The background music will have its own game object as a child of the “Audio_Manager.” I’ll tell you why later!
Calling the Methods
We then need to call the functions to their proper place in the code. I will give an example where.
I have a PowerUp script. It checks if the player collided with it, activates the type of ability, and then destroys the power-up game object.
We want to play the sound before it is destroyed.
First, let's get a reference to our AudioManager script:
private AudioManager _audioManager = null;
We want the PowerUp script to look for the “Audio_Manager” game object and get the attached “AudioManager” script. So let’s find it:
private void Awake()
{
_audioManager = GameObject.Find(“Audio_Manager”).GetComponent<AudioManager>();
}
Now that we have “AudioManager” cached in _audioManager
, we can call the function to play the power-up sound clip. We will call it in OnTriggerEnter2D() where the logic is.
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag(“Player”))
{
var player = other.transform.GetComponent<Player>(); if(player != null)
{
switch (_powerupType)
{
case PowerupType.TripleShot:
player.TripleShotActive();
break;
case PowerupType.Speed:
player.SpeedBoostActive();
break;
case PowerupType.Shield:
player.ShieldActive();
break;
default:
_powerupType = PowerupType.None;
break;
}
} _audioManager.PlayPowerupSound(); Destroy(gameObject);
}
}
In bold, we call the function located in the AudioManager script to play the power-up sound before it is destroyed. It makes sense. We don’t want to call it after the game object is destroyed. It won’t be called.
That is one way of using sound FX for your games. There are many ways to go about this. There is no wrong way of doing things. It’s all a matter of which way is more optimal?
Background Music
For the background music, we want it to play continuously without any interruptions. So we need to separate the audio source from the one AudioManager is referencing and create a new one for the background music.
Create a new empty game object within the “Audio_Manager” game object. We want it to be a child object. Name it “BG_Music.” Attach an “Audio Source” component. Drag the background music audio clip into the “Audio Clip” field, make sure “Loop” and “Play On Awake” are checked. And you’re done!
We now have a simple modular Sound FX system. Congrats! That is all for today! Thank you for reading.