167 lines
4.5 KiB
C#
167 lines
4.5 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
public class BackgroundSoundManager : MonoBehaviour
|
|
{
|
|
public static BackgroundSoundManager Instance { get; private set; }
|
|
public bool isBoss = false;
|
|
[Header("BGM Clips")]
|
|
[SerializeField] private AudioClip normalBGM;
|
|
[SerializeField] private AudioClip battleBGM;
|
|
[SerializeField] private AudioClip victoryBGM;
|
|
[SerializeField] private AudioClip deathBGM;
|
|
|
|
[Header("SFX Clips")]
|
|
[SerializeField] private AudioClip sfxShoot;
|
|
[SerializeField] private AudioClip sfxDeath;
|
|
[SerializeField] private AudioClip sfxHit;
|
|
[SerializeField] private AudioClip sfxCollect;
|
|
[SerializeField] private AudioClip sfxChestOpen;
|
|
|
|
[Header("Settings")]
|
|
[SerializeField] private float fadeDuration = 0.1f;
|
|
[SerializeField] private float defaultVolume = 0.8f;
|
|
[SerializeField] private float victoryDuration = 3f;
|
|
|
|
private AudioSource bgmSource;
|
|
private AudioSource sfxSource;
|
|
private Coroutine fadeCoroutine;
|
|
private Coroutine returnToNormalCoroutine;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
Instance = this;
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
// BGM Source
|
|
bgmSource = gameObject.AddComponent<AudioSource>();
|
|
bgmSource.loop = true;
|
|
bgmSource.playOnAwake = false;
|
|
bgmSource.volume = defaultVolume;
|
|
|
|
// SFX Source
|
|
sfxSource = gameObject.AddComponent<AudioSource>();
|
|
sfxSource.loop = false;
|
|
sfxSource.playOnAwake = false;
|
|
sfxSource.volume = defaultVolume;
|
|
}
|
|
private void Start()
|
|
{
|
|
if(isBoss){
|
|
PlayBattleBGM();
|
|
}else{
|
|
PlayNormalBGM();
|
|
}
|
|
}
|
|
|
|
|
|
// === BGM Controls ===
|
|
public void PlayNormalBGM()
|
|
{
|
|
PlayBGM(normalBGM, true, defaultVolume);
|
|
}
|
|
|
|
public void PlayBattleBGM()
|
|
{
|
|
PlayBGM(battleBGM, true, defaultVolume);
|
|
}
|
|
|
|
public void PlayVictoryBGMThenBackToNormal()
|
|
{
|
|
if (victoryBGM == null) return;
|
|
|
|
StopAllCoroutines(); // Hentikan semua coroutine (fade atau sebelumnya)
|
|
PlayBGM(victoryBGM, false, defaultVolume);
|
|
returnToNormalCoroutine = StartCoroutine(ReturnToNormalAfterVictory());
|
|
}
|
|
|
|
public void PlayDeathBGM()
|
|
{
|
|
if (deathBGM == null) return;
|
|
|
|
StopAllCoroutines();
|
|
PlayBGM(deathBGM, false, defaultVolume);
|
|
}
|
|
|
|
private IEnumerator ReturnToNormalAfterVictory()
|
|
{
|
|
yield return new WaitForSeconds(victoryDuration);
|
|
PlayNormalBGM();
|
|
}
|
|
|
|
private void PlayBGM(AudioClip newClip, bool loop = true, float volume = 1f)
|
|
{
|
|
if (newClip == null) return;
|
|
|
|
if (fadeCoroutine != null)
|
|
StopCoroutine(fadeCoroutine);
|
|
|
|
fadeCoroutine = StartCoroutine(FadeToNewClip(newClip, volume, loop));
|
|
}
|
|
|
|
private IEnumerator FadeToNewClip(AudioClip newClip, float targetVolume, bool loop)
|
|
{
|
|
float startVolume = bgmSource.volume;
|
|
|
|
// Fade out
|
|
for (float t = 0; t < fadeDuration; t += Time.deltaTime)
|
|
{
|
|
bgmSource.volume = Mathf.Lerp(startVolume, 0, t / fadeDuration);
|
|
yield return null;
|
|
}
|
|
|
|
bgmSource.Stop();
|
|
bgmSource.clip = newClip;
|
|
bgmSource.loop = loop;
|
|
bgmSource.Play();
|
|
|
|
// Fade in
|
|
for (float t = 0; t < fadeDuration; t += Time.deltaTime)
|
|
{
|
|
bgmSource.volume = Mathf.Lerp(0, targetVolume, t / fadeDuration);
|
|
yield return null;
|
|
}
|
|
|
|
bgmSource.volume = targetVolume;
|
|
}
|
|
|
|
public void StopBGM()
|
|
{
|
|
if (bgmSource.isPlaying)
|
|
bgmSource.Stop();
|
|
|
|
// Hentikan coroutine yang akan memutar ulang normal BGM
|
|
if (returnToNormalCoroutine != null)
|
|
{
|
|
StopCoroutine(returnToNormalCoroutine);
|
|
returnToNormalCoroutine = null;
|
|
}
|
|
|
|
if (fadeCoroutine != null)
|
|
{
|
|
StopCoroutine(fadeCoroutine);
|
|
fadeCoroutine = null;
|
|
}
|
|
}
|
|
|
|
|
|
// === SFX Controls ===
|
|
private void PlaySFX(AudioClip clip, float volume = 1f)
|
|
{
|
|
if (clip == null) return;
|
|
sfxSource.PlayOneShot(clip, volume);
|
|
}
|
|
|
|
public void PlayShootSFX() => PlaySFX(sfxShoot);
|
|
public void PlayDeathSFX() => PlaySFX(sfxDeath);
|
|
public void PlayHitSFX() => PlaySFX(sfxHit);
|
|
public void PlayCollectSFX() => PlaySFX(sfxCollect);
|
|
public void PlayChestOpenSFX()=> PlaySFX(sfxChestOpen);
|
|
}
|