At some point, every game developer thinks, why is it so quiet?
If your game not built around sounds, such as Osu!, Guitar Hero, or Hotline Miami, you may find yourself in a situation when the game is almost ready, and then you understand: “Something is wrong.” After a couple of minutes of thinking, it turns out that there is no sound in it =) Many people rarely think about such an essential part of the game, and it is not surprising that they can recall it at the very last moment. So let’s talk a little bit about sound.
Sound in Unity
Unity’s audio assets are called AudioClip, and their playback revolves around the two components AudioListener and AudioSource. AudioListener is a component that behaves like a microphone; it picks up all the sounds on the scene and plays them through the speaker. AudioSource - responsible for playing sound on the scene.
Accordingly, for the game to have sound, you need to add the AudioListener component to some object on the scene, and usually, the camera becomes such an object. It should be noted that you can not add more than one listener. Also, you need to add AudioSource components for all sound-reproducing objects.
You can divide the work with sound into three groups:
Background music - we’ll cover it in this article
UI sounds - an acceptable approach would be to add AudioSource components to the necessary UI elements and bind sound playback to their UI events
Sounds in the scene - this group is more complicated than the UI elements because it requires additional mechanisms for adding sounds to dynamic objects. The entire range of possible sounds can be quite large, and listing them in advance is quite problematic. Work with this group requires a separate mechanism and a separate article =)
Goal
Add a mechanism for playing background music. Several tracks should be played one after another, with the possible addition of a delay between them. Provide the possibility of silencing sound (for example, to play ads).
Implementation
We will use singleton as a basis for our music handler. You can read more about singletons in our previous article.
To mute the sound, we use a variable that will track the count of events for muting and returning sounds.
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;publicclassKhtMusicManager:KhtSingleton<KhtMusicManager>{// Delay between tracks
publicintnewTrackDelay=0;// List of tracks
publicList<AudioClip>musicAudioClips=newList<AudioClip>();// Source for playing music
privateAudioSource_musicAudioSource=null;// Used to mute music
privateint_muted=0;protectedoverridevoidAwake(){// Set up singleton
base.Awake();DontDestroyOnLoad(gameObject);// Add component to play music
_musicAudioSource=gameObject.AddComponent<AudioSource>();}// Start is called before the first frame update
voidStart(){// Start playing music
StartCoroutine(PlayBackgroudMusic());}// Mute the music
publicstaticvoidMute(){// Checks for singleton
if(ReferenceEquals(Instance,null)){return;}// If the sound is not muted
if(Instance._muted==0){Instance._musicAudioSource.mute=true;}Instance._muted++;}// Turn on sound
publicstaticvoidTurnOn(){// Check for singleton and skip negative counter
if(ReferenceEquals(Instance,null)||Instance._muted==0){return;}// Turn on the sound
Instance._muted--;if(Instance._muted==0){Instance._musicAudioSource.mute=false;}}// Start the next track
IEnumeratorPlayBackgroudMusic(){// Current track index
intmusicIndex=0;// Play music, if it exists
while(musicAudioClips.Count>0){// Time to start the next track + delay
floatwaitTime=musicAudioClips[musicIndex].length+newTrackDelay;// Play the melody once
_musicAudioSource.PlayOneShot(musicAudioClips[musicIndex]);// Work with the current track index
musicIndex++;if(musicIndex>=musicAudioClips.Count){musicIndex=0;}// Delay to enable the next track
yieldreturnnewWaitForSeconds(waitTime);}}}
Conclusion
The given implementation demonstrates a low entry-level for implementation sound in Unity. The system is quite simple at a basic level; however, if necessary, you can use more advanced components for mixing sounds and applying effects (for example, changing the car engine sound on entering a tunnel). The use of third-party libraries is also a frequent solution. Returning to our implementation, we can highlight the functionality that we would like to add: the ability to start the track by id, stop and restart, randomization. Although each such request is not something complicated, this is beyond the scope of the article, so let’s leave it for the future. See you next time! =)