using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; public class BgmPlaybackManager : MonoBehaviour { public static BgmPlaybackManager Instance { get; private set; } [Header("Audio")] public AudioSource audioSource; public AudioClip clip; [Tooltip("Optional playlist. If empty, will load all clips in Resources/BGM.")] public List playlist = new List(); public int startIndex = 0; [Tooltip("Resources path without extension. Example: BGM/Bansonic OST")] public string resourcesPath = "BGM/Bansonic OST"; [Tooltip("Optional absolute file path to mp3/wav (fallback).")] public string fallbackFilePath = ""; public bool loop = true; public bool autoPlay = true; public string gameplaySceneName = "gamePlay_gamePlay"; public bool stopOnGameplayScene = true; private bool isLoading = false; private int currentIndex = 0; public static BgmPlaybackManager EnsureInstance() { if (Instance != null) return Instance; var go = new GameObject("BGM_PlaybackManager"); Instance = go.AddComponent(); return Instance; } private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); if (audioSource == null) audioSource = gameObject.AddComponent(); audioSource.playOnAwake = false; audioSource.loop = loop; if (clip == null) clip = audioSource.clip; EnsurePlaylist(); if (playlist.Count > 0) { currentIndex = Mathf.Clamp(startIndex, 0, playlist.Count - 1); clip = playlist[currentIndex]; } if (clip != null) audioSource.clip = clip; if (autoPlay) EnsurePlaying(); } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (!stopOnGameplayScene) return; if (scene.name == gameplaySceneName) StopLobbyAudioAndParticles(); } public void EnsurePlaying() { if (audioSource == null) audioSource = gameObject.AddComponent(); audioSource.loop = loop; if (audioSource.clip == null && clip != null) audioSource.clip = clip; if (audioSource.clip == null) { EnsurePlaylist(); if (playlist.Count > 0) { currentIndex = Mathf.Clamp(currentIndex, 0, playlist.Count - 1); audioSource.clip = playlist[currentIndex]; } } if (audioSource.clip == null && !isLoading) { StartCoroutine(LoadClipRoutine()); return; } if (audioSource.clip != null && !audioSource.isPlaying) audioSource.Play(); } private IEnumerator LoadClipRoutine() { isLoading = true; // Try Resources first if (audioSource.clip == null && !string.IsNullOrEmpty(resourcesPath)) { var res = Resources.Load(resourcesPath); if (res != null) { audioSource.clip = res; } } // Fallback to file path if still missing if (audioSource.clip == null) { string path = fallbackFilePath; if (string.IsNullOrEmpty(path)) { // Default to project root /??/Bansonic OST.mp3 var projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); path = Path.Combine(projectRoot, "??", "Bansonic OST.mp3"); } if (File.Exists(path)) { string uri = new System.Uri(path).AbsoluteUri; using (var req = UnityWebRequestMultimedia.GetAudioClip(uri, AudioType.MPEG)) { yield return req.SendWebRequest(); if (req.result == UnityWebRequest.Result.Success) { audioSource.clip = DownloadHandlerAudioClip.GetContent(req); } } } } isLoading = false; if (autoPlay && audioSource.clip != null && !audioSource.isPlaying) audioSource.Play(); } private void EnsurePlaylist() { if (playlist == null) playlist = new List(); if (playlist.Count == 0) { var clips = Resources.LoadAll("BGM"); if (clips != null && clips.Length > 0) { Array.Sort(clips, (a, b) => string.CompareOrdinal(a.name, b.name)); playlist.AddRange(clips); } } } public void PlayIndex(int index) { EnsurePlaylist(); if (playlist == null || playlist.Count == 0) return; currentIndex = (index % playlist.Count + playlist.Count) % playlist.Count; audioSource.clip = playlist[currentIndex]; clip = audioSource.clip; audioSource.loop = loop; audioSource.time = 0f; audioSource.Play(); } public void Next() { EnsurePlaylist(); if (playlist == null || playlist.Count == 0) return; PlayIndex(currentIndex + 1); } public void Previous() { EnsurePlaylist(); if (playlist == null || playlist.Count == 0) return; PlayIndex(currentIndex - 1); } public void TogglePause() { if (audioSource == null || audioSource.clip == null) return; if (audioSource.isPlaying) audioSource.Pause(); else audioSource.Play(); } private void StopLobbyAudioAndParticles() { if (audioSource != null) audioSource.Stop(); } public float CurrentTime => audioSource != null ? audioSource.time : 0f; public float TotalTime => (audioSource != null && audioSource.clip != null) ? audioSource.clip.length : 0f; public bool IsReady => audioSource != null && audioSource.clip != null; }