using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; /// <summary> /// Handles music selections for each menu and level type /// </summary> public class AudioManager : MonoBehaviour { // Singleton Instance of the AudioManager public static AudioManager Instance { get; private set; } [Header("Manager Type")] [SerializeField] bool jungleLevelPlayer; // Reference for if the audio source plays primarily jungle music [SerializeField] List<AudioClip> clipList; // Reference for all of the audio clips necessary for the audio manager attached to the game object AudioSource attachedAudioSource; // Reference for the audio source attached to the game object int lastValue = -1; // Initialize the last value to be -1, -1 is just the chosen parameter to match the iterator in the randomized music selection function since the random range can't be negative int calledIndex; // The level/build index that is currently in scene, if changed will match the current scene index /// <summary> /// Retrieval function to gather the type of music for the type of menu or level that is currently /// being accessed and indicates the type in a text field parameter in the menu screen /// </summary> /// <returns>String for the title in the menu music selector field</returns> public string GetLevelMusic() { if (jungleLevelPlayer) return "Jungle Music"; return "Menu Music"; } public int GetLevelIndex() => calledIndex; /// <summary> /// Sets what type of player the Audio Manager is after each level is loaded to get the correct music playing /// </summary> /// <param name="index">Level Index/Build Index</param> public void SetLevelType(int index) { if (index == 0) // Title Screen return; else if (index > 0 && index <= 15) // Jungle Levels { // This check is called to prevent any stuttering of Jungle music if (jungleLevelPlayer) return; else { jungleLevelPlayer = true; RandomSelection(); } } // Audio Clips are cleared each call of this function unless the manager already shows the player is a specific type clipList.Clear(); // Retrieves the necessary clips from a Resource folder for each type of level AudioClip[] clips; if (jungleLevelPlayer) { clips = Resources.LoadAll<AudioClip>("Jungle/"); foreach (AudioClip clip in clips) clipList.Add(clip); } } /// <summary> /// Retrieves the type of level by value /// </summary> /// <returns>Value of the type of level or menu, Menu returns 0 while Jungle returns 1</returns> public int GetLevelType() { if (jungleLevelPlayer) return 1; return 0; } /// <summary> /// Retrieves the name of the clip name by index to list for the fields in the menu screen /// </summary> /// <param name="index">Index in the clip list array</param> /// <returns>The name of the audio clip gathered by index</returns> public string GetAttachedMusicNameAtPoint(int index) => clipList[index].name; void Awake() { SingletonCreation(); attachedAudioSource = GetComponent<AudioSource>(); } void Start() { SetLevelType(SceneManager.GetActiveScene().buildIndex); } /// <summary> /// Creates a singleton of the audiomanager and handles what sort of audio player is being handled in the specific scene /// </summary> void SingletonCreation() { // Destroys extra Audio Manager reference if (Instance != null) { Destroy(gameObject); return; } // Creates Singleton DontDestroyOnLoad(gameObject); Instance = this; } /// <summary> /// Sets the volume of the attached audio source with the passed volume parameter /// </summary> /// <param name="volume"></param> public void SetVolume(float volume) => attachedAudioSource.volume = volume; /// <summary> /// Sets the state of the audio source loop /// </summary> /// <param name="state"></param> public void SetIsLooping(bool state) => attachedAudioSource.loop = state; void Update() { IndicateLevelType(); PlayMusic(); } /// <summary> /// Checks to see if the level is changed and if so sets the level type and call index /// </summary> void IndicateLevelType() { if (calledIndex != SceneManager.GetActiveScene().buildIndex) { SetLevelType(SceneManager.GetActiveScene().buildIndex); calledIndex = SceneManager.GetActiveScene().buildIndex; } } /// <summary> /// Sets the music based on the name parameter passed through /// </summary> /// <param name="name">Name of the Audio Clip</param> /// <exception cref="ArgumentException">If the name is not found exception is thrown</exception> public void SetMusic(string name) { foreach (AudioClip clip in clipList) { if (clip.name.Equals(name)) // Finds the clip by name then plays it from the beginning { attachedAudioSource.clip = clip; attachedAudioSource.time = 0.0f; attachedAudioSource.Play(); return; } } throw new ArgumentException("Name not indicated within clip list... clip name passed -> " + name); } /// <summary> /// Plays the music based on current state of the audio player /// </summary> void PlayMusic() { if (attachedAudioSource.isPlaying) return; else { RandomSelection(); attachedAudioSource.Play(); } } /// <summary> /// Randomized selection of a clip that was not the previously played clip and then setting the new clip to the audio player attached to the game object /// </summary> void RandomSelection() { int randomValue = -1; // Initialize to -1 to match the beginning last value parameter // Get random clip from the audio clip list except for the previous clip played and play it do { randomValue = UnityEngine.Random.Range(0, clipList.Count); } while (randomValue == lastValue); lastValue = randomValue; // Last value is set to the now new random value attachedAudioSource.clip = clipList[randomValue]; // Clip for the attached audio source is set to the clip in the list based on the random value } }