using TMPro; using System; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class MainMenu : MonoBehaviour { public static bool IsPaused; // Static indicator for if the game should pause due to the main menu opening [Header("Canvas Attributes")] [SerializeField] Canvas menuCanvas; // Reference to the primary menu canvas [SerializeField] Canvas optionsCanvas; // Reference to the secondary options canvas [Header("Options Canvas Attributes")] [SerializeField] TextMeshProUGUI musicTextField; // Reference for the text field that changes between specific level types [SerializeField] RectTransform contentRect; // Reference for the content rectangle that the music buttons will be located in [SerializeField] GameObject musicButtonPrefab; // Refernece for the music button prefab used in the music selection part of the options screen [SerializeField] Slider volumeSlider; // Reference to the volume slider for the player volume preferences [SerializeField] Toggle loopingToggle; // Reference to the looping toggle value AudioManager musicManager; // Reference to the current scene's audio manager int currentIndex; void Awake() { // Checks if player prefs are available if (!PlayerPrefs.HasKey("Volume")) PlayerPrefs.SetFloat("Volume", .7f); // Volume aspect is set to around 70 percent if (!PlayerPrefs.HasKey("Looping")) PlayerPrefs.SetInt("Looping", 0); // 0 to false for the looping aspect } void Start() { musicManager = AudioManager.Instance; InitiatePlayerPreferences(); if (musicManager.GetLevelMusic().Equals(string.Empty)) // If the scene does not have a specific level name simply return { Guard Clause } return; else // Sets the music text field for the options screen upon game start musicTextField.text = musicManager.GetLevelMusic(); // Indicates the name of each music option available for the level string[] nameList = ShowMusicList(); // Instantiate enough buttons to create a list of various music selections for the user to choose foreach (string name in nameList) { GameObject reference = Instantiate(musicButtonPrefab, contentRect); reference.GetComponentInChildren<TextMeshProUGUI>().text = name; reference.GetComponent<Button>().onClick.AddListener(() => ChangeMusic(name)); } } void RefreshMusicList() { musicTextField.text = musicManager.GetLevelMusic(); string[] nameList = ShowMusicList(); foreach (Transform trans in contentRect) { Destroy(trans.gameObject); } foreach (string name in nameList) { GameObject reference = Instantiate(musicButtonPrefab, contentRect); reference.GetComponentInChildren<TextMeshProUGUI>().text = name; reference.GetComponent<Button>().onClick.AddListener(() => ChangeMusic(name)); } } /// <summary> /// Initiates the volume and looping preferences for the player's music /// </summary> void InitiatePlayerPreferences() { // Initiates the player preferences for the player such as volume and looping musicManager.SetVolume(PlayerPrefs.GetFloat("Volume")); volumeSlider.value = PlayerPrefs.GetFloat("Volume"); // Checks if the player pref for looping the selected music is enabled and if so to set the loop, otherwise set it to false if (PlayerPrefs.GetInt("Looping") == 0) { SetMusicLoop(false); loopingToggle.isOn = false; } else { SetMusicLoop(true); loopingToggle.isOn = true; } } void Update() { CheckLevelIndex(); if (Input.GetKeyDown(KeyCode.Escape) && SceneManager.GetActiveScene().buildIndex != 0) { IsPaused = !IsPaused; // The static variable for if the other objects in the scene should be paused is switched to the opposite of the current value of the variable if (IsPaused) PauseGame(); // Pause else UnpauseGame(); // Unpause } } void CheckLevelIndex() { if (musicManager.GetLevelIndex() != currentIndex) { currentIndex = musicManager.GetLevelIndex(); RefreshMusicList(); } } /// <summary> /// Freezes the time scale as well as opens the main menu while playing /// </summary> void PauseGame() { Time.timeScale = 0f; menuCanvas.enabled = true; } /// <summary> /// Unfreezes the time scale as well as closes the menu while playing. Made public for accessibility with the close button on the canvas /// </summary> public void UnpauseGame() { Time.timeScale = 1f; menuCanvas.enabled = false; optionsCanvas.enabled = false; if (IsPaused) IsPaused = false; // For the exit button at the top of the menu being used } /// <summary> /// Loads the Title Screen /// </summary> public void GoToTitleScreen() => SceneManager.LoadScene("MainMenu"); /// <summary> /// Quit the application /// </summary> public void ExitGame() => Application.Quit(); /// <summary> /// Sets the player prefs volume for the user's system /// </summary> /// <param name="volume">Float parameter based on the slider in the options menu</param> public void ChangeVolume(float volume) { PlayerPrefs.SetFloat("Volume", volume); musicManager.SetVolume(volume); } /// <summary> /// Creates a list of names based on the audio clips in the current scene /// </summary> /// <returns>String list of the current names of the audio clips in the scene</returns> /// <exception cref="IndexOutOfRangeException">The value of the parameter gathered from the level type retrieval prompted a strange behaviour</exception> public string[] ShowMusicList() { int int_Parameter = musicManager.GetLevelType(); if (int_Parameter == 0) // Menu Music return GenerateMusicList(3); else if (int_Parameter == 1) // Jungle Music return GenerateMusicList(3); throw new IndexOutOfRangeException("Unexpected int_Parameter value in ShowMusicList. int_Parameter = " + int_Parameter); } /// <summary> /// Expect a list of names based on the parameter passed from the audio manager audioclips list /// </summary> /// <param name="numberOfNames">Number of names to be expected</param> /// <returns>List of audioclip names from the current scene audioclip list</returns> /// <exception cref="Exception">Out-Of-Range Exception</exception> string[] GenerateMusicList(int numberOfNames) { string[] musicList = new string[numberOfNames]; try // Take each value in the list of audio clips from the audio manager and create a list of names from the manager { for (int i = 0; i < numberOfNames; i++) musicList[i] = musicManager.GetAttachedMusicNameAtPoint(i); } catch (Exception e) { throw new Exception("Number of names expected is out of range of what is available in the AudioManager. numberOfNames = " + numberOfNames, e); } return musicList; } /// <summary> /// The music changes to the audio clip based on the name passed through the function /// </summary> /// <param name="audioClipName">Name of the Audio Clip that is being called</param> public void ChangeMusic(string audioClipName) => musicManager.SetMusic(audioClipName); /// <summary> /// The music loops depending on the state parameter passed /// </summary> /// <param name="state">Sets if the music is looping or is not looping</param> public void SetMusicLoop(bool state) { musicManager.SetIsLooping(state); if (state) PlayerPrefs.SetInt("Looping", 1); else PlayerPrefs.SetInt("Looping", 0); } }