Implementing Audio for a Prototype FPS in Unity 2021
In this article we’ll implement an Audio Manager in our FPS prototype.
First, create an AudioManager script and add the necessary variables for audio sources and audio clips.
As triggered audio events and the background audio will overlap, these will use different audio sources.
We’ll create a public method for each audio event and play the associated audio clip in these methods.
In the Unity Editor, we need to create an Audio_Manager empty game object and a childed BackgroundMusic empty game object.
We’ll attach the AudioManager script to the Audio_Manager game object and assign the audio files to the component.
We’ll also add an Audio Source component and disabled the “Play On Awake” and “Loop” fields.
We’ll then add an Audio Source to the BackgroundMusic game object and assign the audio clip to it.
This we’ll allow to play on awake and loop.
In the Player script, we’ll add a new UnityEvent, “playerFiredWeapon”.
We’ll invoke this Unity Event in the FireWeapon() method.
Now we can assign our AudioManager.PlayerFiredRifle() method to the Unity Event on the Player script component.
If we run the game in play mode, we’ll now hear background music playing and a gunshot fired when the player shoots.
In our Player script, we can add another UnityEvent for when the raycast detects it has hit cover.
As our cover game objects are assigned to layer 10, we can make use of our commented out code from earlier articles that check the raycast’s hit layer.
We simply invoke our new Unity Event and return to the Unity Editor.
Once again, we assign our UnityEvent the associated public method from the Audio_Manager game object’s AudioManager script component.
If we hit play, this is working.
However, the cover impact sound is pretty much cancelling the shot fired sound.
This works, but my audio clip for the cover impact is louder than I’d like.
Since the same audio source is shared for the bullet fired audio and the cover hit audio, I’ll need to modify the volume and reset it.
To add a delay to the cover hit audio, we’ll use a coroutine as shown above.
To make this more robust and allow a game designer to modify the volume level from the script component rather than on the audio source, I’ve added a range defined float variable to the AudioManager script.
Since an Audio Source’s volume is clamped between 0 and 1 as a float, I defined my variable to match.
When shown in the Unity Editor, Unity actually creates a nice slider feature for this field just like the one in the Audio Source Volume field itself.
After a bit of testing, this is the end result of the newly created CoverImpactDelay() coroutine.
Using Debug.Log confirmed the volume did change before playing.
I then reset the volume to normal after playing the cover impact hit audio clip.
This may not be necessary for your audio clips, but it’s good to know how to handle this situation.
In the RobotAI script, I’ve added a new Unity Event for when the AI reaches the end of the level.
Since there is already a ReachedEnd() method that fires off when this occurs, placing the invoke for this new Unity Event is pretty simple.
Here, we run into a limitation of the UnityEvent sytem.
It seems that we cannot assign an invoke call to a prefab, but only a game object in the scene.
There are two approaches to solve this issue.
One, I could write code logic to assign this Unity Event after each RobotAI spawns.
This is probably more CPU expensive and time consuming to implement than the second approach though.
Two, I can move my UnityEvent and invocation to the SpawnManager script.
The SpawnManager script is always in the scene and also already tracks when each AI reaches the end of the level.
Now, we can test out our new approach.
Sweet, as each AI reaches the trigger zone, we can hear the correct audio cue playing.
Now, we do have a couple more audio clips that need to be completed.
However, as we have not implemented our win/lose scenario logic yet, this will have to wait!
See you in the next article, thanks for reading!