using UnityEngine; using System.Linq; using System.Collections; using System.Collections.Generic; /// /// Sound manager for Tearable World. Uses AudioSources and attaches them to one object. /// Has all of the basic controls and allows for two types, SFX and MUSIC. /// /// Created by Douglas Weller - 2/1/13-present /// public class SoundManager : MonoBehaviour { #region Variables #region Sound Variables /// /// A pre-declared audiosource, so you don't have to declare one throughout the code /// constantly. /// AudioSource audioSourceTemp; //list of sounds fading in and out private List fadeInSounds; private List fadeOutSounds; /// /// Dictionary filled with the music audiosources, so you /// can look for and play it based on the string of the sound name /// private Dictionary myMusicSounds; /// /// Dictionary filled with the sfx audiosources, so you /// can look for and play it based on the string of the sound name /// private Dictionary mySFXSounds; /// /// The next open musicSounds array point. /// private int musicLength = 0; /// /// The next open point in array of SFX. /// private int sfxLength = 0; /// /// This is the current music vol. /// public float musicVol = 1.0f; /// /// This is the current sfx vol. /// public float sfxVol = 1.0f; /// /// List of sfx clips that have already been added, used when /// you call LoadAudioAssets. /// List alreadyHereSFXClips; /// /// List of music clips that have already been added, used when /// you call LoadAudioAssets. /// List alreadyHereMusicClips; // private AnimationManager animManagerRef; // private InputManager inputManagerRef; // private GameStateManager gameStateManagerRef; // private TWCharacterController controllerRef; #endregion #endregion #region Basic Functions // Use this for initialization void Start () { //DontDestroyOnLoad(gameObject); } // Update is called once per frame void Awake() { if(gameObject.GetComponent() == null) gameObject.AddComponent(); myMusicSounds = new Dictionary(); mySFXSounds = new Dictionary(); fadeInSounds = new List(); fadeOutSounds = new List(); alreadyHereSFXClips = new List(); alreadyHereMusicClips = new List(); } void Update () { //All fade code written by Justin Telmo, team member. if (fadeOutSounds.Count > 0) { UnityEngine.Debug.Log(fadeOutSounds.First().name); foreach (AudioSource audio in fadeOutSounds) { if (audio.volume > 0.1) { audio.volume -= 0.1f * Time.deltaTime; } } } if (fadeInSounds.Count > 0) { foreach (AudioSource audio in fadeInSounds) { while (audio.volume < 1) { audio.volume += 0.1f * Time.deltaTime; } } } } #endregion #region Load /// /// Load all sounds in music and sfx folders to empty sfx and music arrays /// as audioclips, then declare size of audiosource arrays for /// music and sfx based on amount of audio pulled /// public void LoadAllAudioAssets() { List tempClips = Resources.LoadAll ("Audio/Music", typeof(AudioClip)).Cast().ToList(); foreach(AudioClip ac in tempClips) AddMusicSound(ac); tempClips = Resources.LoadAll ("Audio/SFX", typeof(AudioClip)).Cast().ToList(); foreach(AudioClip ac in tempClips) AddSFXSound(ac); } /// /// Loads the the list of given strings for music and sfx /// /// /// List of string names of songs to be loaded /// /// /// List of SFX names to be loaded /// public void LoadAudioAssets(List musList, List sfxList) { AudioClip audioClipTemp; RemoveSounds(musList, sfxList); foreach(string s in musList) { if(!alreadyHereMusicClips.Contains(s)) { audioClipTemp = Resources.Load("Audio/Music/"+s, typeof(AudioClip)) as AudioClip; if(audioClipTemp) { AddMusicSound(audioClipTemp); } } } foreach(string s in sfxList) { if(!alreadyHereSFXClips.Contains(s)) { audioClipTemp = Resources.Load("Audio/SFX/"+s, typeof(AudioClip)) as AudioClip; if(audioClipTemp) { AddSFXSound(audioClipTemp); } } } audioClipTemp = null; audioSourceTemp = null; alreadyHereSFXClips.Clear(); alreadyHereMusicClips.Clear(); Resources.UnloadUnusedAssets(); } private void RemoveSounds(List musList, List sfxList) { alreadyHereSFXClips.Clear(); alreadyHereMusicClips.Clear(); //list of the names of audioclips to be removed from current music and sfx lists List toRemove = new List(); //look through each sound name in myMusicSounds //and determine whether it should stay or not //This is both to find music that is already there //as well as dealing with songs that aren't in the list of //new songs that need to be removed foreach(string cn in myMusicSounds.Keys) { bool chosen = false; for(int i = 0; i < musList.Count; i++) if(cn == musList[i]) chosen = true; if(!chosen) toRemove.Add(cn); else alreadyHereMusicClips.Add(cn); } //now look through the sounds to remove, and //double check that it in fact exists in the music list //then remove it foreach(string sndName in toRemove) { //checks that the sound is there if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.Stop(); //stops the sound fadeInSounds.Remove(audioSourceTemp); //begins removing references to it myMusicSounds.Remove(sndName); Destroy(audioSourceTemp);//destroy the object audiosource } } //clear the list to check for sfx toRemove.Clear(); //look through each sound name in mySFXSounds //and determine whether it should stay or not foreach(string cn in mySFXSounds.Keys) { bool chosen = false; for(int i = 0; i < sfxList.Count; i++) if(cn == sfxList[i]) chosen = true; if(!chosen) toRemove.Add(cn); else alreadyHereSFXClips.Add(cn); } //now look through the sounds to remove, and //double check that it in fact exists in the music list //then remove it foreach(string sdName in toRemove) { if(mySFXSounds.TryGetValue(sdName, out audioSourceTemp)) { //Debug.Log(audioSourceTemp.clip.name); audioSourceTemp.Stop(); fadeInSounds.Remove(audioSourceTemp); mySFXSounds.Remove(sdName); Destroy(audioSourceTemp); //destroy the object audiosource } } } #endregion #region Add Sounds /// /// Adds the AudioClip given to the AudioSource array based on type. /// Type is either "MUSIC" or "SFX" /// /// /// /// The clip to be added to list of music audiosources /// /// /// Type. /// private void AddMusicSound(AudioClip clip) { if(!myMusicSounds.ContainsKey(clip.name))//double check the sound hasn't already been added { AudioSource temp; temp = gameObject.AddComponent(); //add an audiosource to main game object temp.name = clip.name; //make name of audio source same as the clip temp.clip = clip; //set clip temp.volume = musicVol; //set the volume to whatever musicvol currently is temp.loop = true; //makes the music loop myMusicSounds.Add(clip.name, temp); } } private void AddSFXSound(AudioClip clip) { if(!mySFXSounds.ContainsKey(clip.name)) { AudioSource temp; temp = gameObject.AddComponent();//add an audiosource to main game object temp.clip = clip; //set clip temp.volume = sfxVol; //make the sfx set to the current sfx vol temp.loop = false; //makes the sfx not loop temp.name = clip.name;//make name of audio source same as the clip mySFXSounds.Add(clip.name, temp); } } #endregion #region Volume /// /// Checks the type of sound "SFX" or "MUSIC". /// sndName is the name of the clip you want to stop. /// It then calls SetVolForSpecificSnd. /// /// /// Vol. /// /// /// Snd name. /// /// /// Type. /// public void SetSpecificSoundVol(float vol, string sndName) { //checks if the sound is in music list if (myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.volume = vol; //if it is it set it to a new vol. return; } else //otherwise it checks the sfx sounds { if (mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.volume = vol; //if sounds there it set it to new vol. return; } } //well send out error if the sound isn't there, but it won't stop the game from running Debug.LogError("No Music Sound Called " + sndName + " found."); } /// /// Sets the SFX vol. /// /// /// Vol. /// public void SetSFXVol(float vol) { sfxVol = vol; //set SFX vol for all new sfx added. foreach (AudioSource m in mySFXSounds.Values) m.volume = vol; } /// /// Sets the music vol. /// /// /// Vol. /// public void SetMusicVol(float vol) { musicVol = vol;//set music vol for all new music added //loop through music and set volume for each one to vol foreach(AudioSource m in myMusicSounds.Values) m.volume = vol; } /// /// Returns the current music volume. /// /// /// The current music volume. /// public float GetMusicVol() { return musicVol; } /// /// Returns the current sound effects volume. /// /// /// The current sound effects voluem. /// public float GetSFXVol() { return sfxVol; } #region Mute /// /// Mutes all sounds. /// /// /// The all. /// public void MuteAll() { //sfxSound.mute = true; //for(int i = 0; i < sfxLength; i++) // sfxSound[i].mute = true; foreach(AudioSource m in myMusicSounds.Values) m.mute = true; foreach(AudioSource m in mySFXSounds.Values) m.mute = true; } /// /// Unmutes all the sounds. /// /// /// The mute all. /// public void UnMuteAll() { //sfxSound.mute = false; //for(int i = 0; i < sfxLength; i++) // sfxSound[i].mute = false; foreach(AudioSource m in myMusicSounds.Values) m.mute = false; foreach(AudioSource m in mySFXSounds.Values) m.mute = false; } #endregion #endregion #region Stop, Pause, Play #region Play /// /// Plays specified audiosource /// Needs to know type, either "MUSIC" or "SFX" /// /// /// Source. /// public void PlayAudio(string sndName, string type) { if(type == "MUSIC")//checks if its a music clip we want to play { if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.Play(); // if it exists play it return; } } else if(type == "SFX")//checks if its a music clip we want to play { if(mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.Play();// if it exists play it return; } } //log error if the song doesn't exist in the specified area Debug.Log ("Failed to play " + sndName + " of type: " + type); } /// /// Plays an audio clip and throws it out there for /// a one-time use. This means that the sound can be played /// multiple times without worrying about it stopping the previous version. /// THe problem is you can't control it anymore, so the sound will play until /// it ends (which for music is never). /// /// /// public void PlayAudioOneShot(string sndName, string type) { if(type == "SFX") { if(mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.PlayOneShot(audioSourceTemp.clip); return; } } else if(type == "MUSIC") { if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.PlayOneShot(audioSourceTemp.clip); return; } } Debug.Log ("Failed to play one shot " + sndName + " of type: " + type); } /// /// Determines whether this sound is playing currently /// /// /// The name of the sound we want to check /// /// /// String of type "SFX" or "MUSIC" /// public bool IsAudioPlaying(string sndName, string type) { //UnityEngine.Debug.Log("Calling isAudioPlaying"); if (type == "MUSIC") { if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { if(audioSourceTemp.isPlaying) return true; else return false; } } else if (type == "SFX") { if (mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { if (audioSourceTemp.isPlaying) return true; else return false; } } return false; } #endregion #region Stop /// /// Stops specific sound, determined by AudioSource /// Needs to know type, either "MUSIC" or "SFX" /// Stop means that the music is stopped. When you play it again it will start from the beginning. /// /// /// Source. /// public void StopSound(string sndName, string type)//change string sndname to audiosource source if reverting to old code { if(type == "MUSIC") { if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.Stop(); return; } } else if(type == "SFX") { if(mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { UnityEngine.Debug.Log("We stopped: " + sndName); audioSourceTemp.Stop(); return; } //Debug.LogError("cannot stop sfx"); return; } Debug.LogError("SoundManager: " + sndName + " sound not located for StopSound of type " +type); } /// /// Stops all sounds, so when sound plays again it will start from beginning. /// public void StopAll() { foreach(AudioSource m in myMusicSounds.Values) m.Stop(); foreach (AudioSource m in mySFXSounds.Values) m.Stop(); } #endregion #region Pause /// /// Pauses specific sound, determined by AudioSource. Needs to know type /// either "MUSIC" or "SFX" /// Pause means that after being paused, the song will continue from that point /// when played again. /// /// /// Source. /// public void PauseSound(string sndName, string type)//change string sndname to audiosource source if reverting to old code { if(type == "MUSIC") { if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.Pause(); return; } } else if(type == "SFX") { if (mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.Pause(); return; } return; } Debug.LogError("SoundManager: " + sndName + " sound not located for PauseSound of type " + type); } /// /// Pauses all music in musicSounds, so when music play they will begin from where they were paused. /// public void PauseAllSounds() { foreach(AudioSource m in myMusicSounds.Values) m.Pause(); foreach (AudioSource m in mySFXSounds.Values) m.Pause(); //Debug.Log ("SoundManager: all music paused"); } #endregion #region Fades /// /// Fades a given sound effect or song out. /// Created by Justin Telmo, team member /// /// /// public void FadeOut(string sndName, string type) { if (type == "MUSIC") { if (myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { fadeOutSounds.Add(audioSourceTemp); } } if (type == "SFX") { if (mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { fadeOutSounds.Add(audioSourceTemp); } } Debug.Log("Failed to begin fadeout of " + sndName + " of type " + type); } /// /// Fades a given sound effect or song in from zero. /// made by justin telmo, team member /// /// /// public void FadeIn(string sndName, string type) { if (type == "MUSIC") { if (myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { fadeInSounds.Add(audioSourceTemp); } } if (type == "SFX") { if (mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { fadeInSounds.Add(audioSourceTemp); } } Debug.Log("Failed to begin fadein of " + sndName + " of type " + type); } #endregion #endregion #region Pitch /// /// This sets the pitch for a specific sound. /// Pitch is the speed at which the sound plays, so 1 is regular, 2 is double, .5 is half. /// The sndName is the clip name you want to change. /// Types are "MUSIC" or "SFX" /// public void SetSndPitch(string sndName, float pitch, string type) { //check type if(type == "MUSIC") { if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.pitch = pitch; return; } } //check type else if(type == "SFX") { if (mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { audioSourceTemp.pitch = pitch; return; } return; } Debug.LogError("error setting pitch of " +sndName+ " of type " + type); } /// /// Returns the pitch of the clip that has the same name as sndName, that is in type "MUSIC" or "SFX" /// Pitch is the speed at which the sound plays, so 1 is regular, 2 is double, .5 is half. /// /// /// The snd pitch. /// /// /// Snd name. /// /// /// Type. /// public float GetSndPitch(string sndName, string type) { if(type == "MUSIC") //check type { if(myMusicSounds.TryGetValue(sndName, out audioSourceTemp)) { return audioSourceTemp.pitch; } } else if(type == "SFX")//check type { if (mySFXSounds.TryGetValue(sndName, out audioSourceTemp)) { return audioSourceTemp.pitch; } } Debug.LogError("Unable to get sndpitch of " + sndName+ " of type " + type); return 0.0f; } #endregion }