using System.Collections; using System.Collections.Generic; using UnityEngine; using Game; using Music; using Player; using UnityEngine.SceneManagement; namespace Music { /// /// Manages the music playlists for the game. /// Handles the initialization, playback, and shuffling of music tracks based on the active scene. /// public class MusicManager : MonoBehaviour { /// /// A singleton instance of the class. /// Ensures only one instance of the MusicManager exists at a time. /// public static MusicManager Instance; /// /// A list of playlists available in the game. /// public List playlists; /// /// A dictionary mapping scene names to their corresponding playlists. /// private Dictionary sceneToPlaylist = new Dictionary(); /// /// The prefab used to create audio sources for playing songs. /// public GameObject songPrefab; /// /// Ensures only one instance of the MusicManager exists and initializes the scene-to-playlist mapping. /// private void Awake() { if (Instance == null) { Instance = this; } else { Destroy(this.gameObject); } foreach (Playlist playlist in playlists) { foreach (string scene in playlist.trackScenes) { sceneToPlaylist.Add(scene, playlist); } } } /// /// Starts the music playlist for the current active scene. /// public void StartPlaylist() { if (GetActiveSceneNotTitleScreen() == "Player Select") return; StopAllCoroutines(); foreach (Transform child in transform) { Destroy(child.gameObject); } try { StartCoroutine(PlayPlaylist(sceneToPlaylist[GetActiveSceneNotTitleScreen()])); } catch (System.Exception) { print("No playlist found for this scene: " + GetActiveSceneNotTitleScreen()); } } /// /// Starts the music playlist for a specific scene. /// /// The name of the scene for which to start the playlist. public void StartPlaylist(string scene) { if (GetActiveSceneNotTitleScreen() == "Player Select") return; StopAllCoroutines(); foreach (Transform child in transform) { Destroy(child.gameObject); } StartCoroutine(PlayPlaylist(sceneToPlaylist[scene])); } /// /// Plays the specified playlist by shuffling and playing its songs in sequence. /// /// The playlist to play. /// An enumerator for the coroutine. private IEnumerator PlayPlaylist(Playlist playlist) { while (true) { // Shuffle the playlist List randomized = new List(playlist.songs); for (int i = 0; i < randomized.Count; i++) { AudioClip temp = randomized[i]; int randomIndex = Random.Range(i, randomized.Count); randomized[i] = randomized[randomIndex]; randomized[randomIndex] = temp; } // Play each song in the shuffled playlist foreach (AudioClip song in randomized) { AudioSource songInstance = Instantiate(songPrefab, transform).GetComponent(); songInstance.clip = song; songInstance.volume = playlist.volume; songInstance.Play(); if (playlist.shuffleTime > 0f) { yield return new WaitForSeconds(playlist.shuffleTime); float time = 0f; while (time < 5f) { songInstance.volume = playlist.volume * (1 - time / 5f); time += Time.deltaTime; yield return null; } } else { yield return new WaitForSeconds(song.length); } Destroy(songInstance.gameObject); } } } /// /// Gets the name of the currently active scene, excluding the "Title Screen". /// /// The name of the active scene, or "Title Screen" if no other scene is active. public static string GetActiveSceneNotTitleScreen() { for (int sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++) { if (SceneManager.GetSceneAt(sceneIndex).name != "Title Screen") { return SceneManager.GetSceneAt(sceneIndex).name; } } return "Title Screen"; } } }