Homebound / Scripts / AudioManager.cs
AudioManager.cs
Raw
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
    }
}