Introduction
Another day and another post! In today’s post, we’re going to look into how we would go about adding sound effects into our game. Our goal today is to:
- Get a simple coin pick up sound effect
- Create a
SoundManager
class that will house all of our sound effects/background music - Play the sound effect
For long time readers, I’m sure you’ll recognize most of the code that we’re going to write! Today’s post should be short. Let’s get started!
Step 1: Finding a Music Asset
The first thing we need to do is find a music asset that we can use. I’m not a musician and I’m not really interested in learning how to make my own music assets right now, so let’s just take a royalty free sound effect from the internet!
The first place I turn to for some free assets to play around with is freesound.org, it’s even in the name!
We just want a simple coin pickup sound asset and here’s what I found:
Coins 1 from user ProjectsU012
:
It’s a simple pick up sound. You must make an account to download the music file.
Once you have the file:
- Drag and drop directly into the project in Unity
- Rename it from
341695__projectsu012__coins-1
to Pickup Coin
Step 2: Playing Sound with the SoundManager!
Step 2.1: Creating the SoundManager
The next thing we need to do is to play the sound asset that we added! Following the manager designs that we have been using, we’re going to create a Sound Manager class that our scripts can use to play sounds.
Normally, I would say the manager would follow the same singleton pattern that we’re used to seeing, it’s not the case here for our 3D game. Specifically, for 3D games, you shouldn’t hear any sound if you’re too far away. Whereas in 2D, it might not matter as much.
The sound in Unity is played by using the Audio Source component and there’s an option in there to specify a distance for sound. And to know the distance, we actually need the Audio Source to play from the location where it is generated.
What this means is that instead of having a singleton Sound Manager, we instead need to have individual instances of the Sound Manager script for each game
object that needs to play sound.
Let’s create our SoundManager
script:
In Coin Container in the hierarchy, create a new script called SoundManager
.
Here’s what the SoundManager
script looks like:
using UnityEngine;
public class SoundManager : MonoBehaviour {
private AudioSource _sfxSource;
private AudioSource _bgmSource;
void Awake()
{
_sfxSource = gameObject.AddComponent<AudioSource>();
_bgmSource = gameObject.AddComponent<AudioSource>();
}
public void PlayBackgroundClip(AudioClip audioClip)
{
_bgmSource.clip = audioClip;
_bgmSource.Play();
}
public void StopBackgroundClip()
{
if (_bgmSource.isPlaying)
{
_bgmSource.Stop();
}
}
public void PlaySFXClip(AudioClip audioClip)
{
_sfxSource.PlayOneShot(audioClip);
}
}
Looking at the Fields
We have 2 fields that we’re using for our SoundManager
:
private AudioSource _sfxSource
– This is the AudioSource
that is used to play our sound effects. private AudioSource _bgmSource
– This is the AudioSource
that is used to play our background music.
The inspiration for me to have multiple AudioSource
components is from this question about playing multiple sounds from the same AudioSource. It turns out, you can have as many AudioSource
that you want, you can only have 1 AudioListener
per scene.
Each AudioSource
can only play one continuous sound in the background, that’s why we have 2 AudioSource
s, one to play the background music and another to play any sound effects that we want to add.
Walking Through the Code
In the code, rather than trying to grab an existing AudioSource component, we’re going to create it via code instead. By doing this, we don’t have to worry about adding the AudioSource
manually to every game object and we can instead just add the AudioClips
.
- In
Awake()
, we create our 2 AudioSource
. We can do this by calling AddComponent()
from our gameObject
. This function accepts and returns the type of the component we want to attach. In this case, we add and receive a reference to the AudioSource
that we added. PlayBackgroundClip()
is a public
function that other scripts can call that takes in an AudioClip
of the background music we want to play. Currently, we have no background music, but we might add some and this functionality will make it very easy for us! StopBackgroundClip()
is another public
function similar to PlayBackgroundClip()
that we call to stop playing the background music that we set. PlaySFXClip()
is another public
function that other scripts can call that takes in a short sound effect AudioClip
that we will use PlayOneShot()
. What this does is that it allows multiple audio clips to be played using shared settings for our AudioSource
.
We might need to add some new functionality to the SoundManager
and add setting configurations to the AudioSource
, but let’s just add a basic skeleton of what we want for now.
Setting Up the Environment
After we have our script in, we need to:
Click Apply in the Coin Container game, to include the new SoundManager
script to our Coin Container prefab we created.
If it isn’t clear why, this is to make sure when we generate coins using the prefab, they will all have the SoundManager
script.
Step 2.2: Using the SoundManager
Now that we have added our SoundManager
to play Audio
, we still need a script to use it.
We’re going to update our existing Coin
script to play an audio when a coin
gets collected.
Here’s what our Coin
script looks like now:
using UnityEngine;
using System.Collections;
public class Coin : MonoBehaviour
{
public AudioClip CollectCoinSFX;
private SoundManager _soundManager;
void Start()
{
_soundManager = GetComponent<SoundManager>();
}
public void Collect() {
_soundManager.PlaySFXClip(CollectCoinSFX);
StartCoroutine(RemoveGameObject());
}
private IEnumerator RemoveGameObject()
{
yield return new WaitForSeconds(0.1f);
Destroy(gameObject);
}
}
Looking at the Fields
We introduced 2 fields for our script:
public AudioClip CollectCoinSFX
– This is to store the CoinCollection
sound effect that we just recently added that we will pass to the private SoundManager _soundManager
– This is used to play the CollectCoinSFX
that we are adding.
Walking Through the Code
- In
Start()
, we grabbed an instance of the SoundManager
script and set it to _soundManager
. - In
Collect()
, which we call from our PlaneCollider
script when we collide against the coin, we would use our SoundManager
to play the sound effect and then fire our RemoveGameObject()
. - In
RemoveGameObject()
, we wait 0.1 seconds and then we destroy the game
object. If we were to immediately destroy the game
object after we play the sound, the sound would never have the chance to be played. That’s why we have to wait to have the sound get played and then remove the game object from the scene.
Setting Up the Environment
Now that we have the script, we just need to add the public AudioClip
.
- In the Collect Coin SFX slot in the
Coin
script, drag and drop our Pickup Coin.wav into it. - Make sure to hit the Apply button in the inspector to save this to our prefab.
Step 2.3: Adding an Audio Listener
Now the last piece to the puzzle of adding audio is to create an AudioListener
component to our player character.
Select Player from the game hierarchy and then add a new Audio Listener component to the game
object.
Day 82 Summary
That’s it! Today, we added the first sound effect in the game. If you were to play the game now and collide against a coin, you’ll be able to hear the sound effect that we added.
To recap what we did today:
- We created a
SoundManager
script that will be applied to every game
object that wants to play sound. - We added our first
coin
pick up sound effect whenever we collide against a coin game
object.
In the next post, we’re going to start adding the remaining sound effects that we’re missing with our new sound manager.
Day 81 | 100 Days of VR | Day 83
Home
CodeProject
The post Day 82 of 100 Days of VR: Endless Flyer – Adding Pickup Sound Effects appeared first on Coding Chronicles.