Files
bansonic_beta_main/Assets/scripts/Audio/BgmPlaybackManager.cs
T

236 lines
6.6 KiB
C#

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<AudioClip> playlist = new List<AudioClip>();
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<BgmPlaybackManager>();
return Instance;
}
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
if (audioSource == null)
audioSource = gameObject.AddComponent<AudioSource>();
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 && scene.name == gameplaySceneName)
{
StopLobbyAudioAndParticles();
return;
}
// Ensure lobby/select scenes resume BGM after returning from gameplay.
if (autoPlay)
EnsurePlaying();
}
public void EnsurePlaying()
{
if (audioSource == null)
audioSource = gameObject.AddComponent<AudioSource>();
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<AudioClip>(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<AudioClip>();
if (playlist.Count == 0)
{
var clips = Resources.LoadAll<AudioClip>("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;
}