236 lines
6.6 KiB
C#
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;
|
|
}
|