96 lines
3.1 KiB
C#
96 lines
3.1 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Audio;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public class AudioManager : MonoBehaviour, ISceneInitializable
|
|
{
|
|
public static AudioManager Instance;
|
|
|
|
public AudioMixer mainMixer;
|
|
public AudioSource bgmAudioSource;
|
|
public AudioClip StartSceneBgm;
|
|
public AudioClip GameSceneBgm;
|
|
public AudioClip BossSceneBgm;
|
|
|
|
|
|
// ─── SFX ─────────────────────────────────────────────────────────────
|
|
[Header("SFX")]
|
|
public AudioMixerGroup sfxGroup; // SFX를 라우팅할 믹서 그룹 (Inspector에서 연결)
|
|
public int sfxSourceCount = 12; // 미리 만들어둘 AudioSource 풀 크기 (동시 재생 가능 수)
|
|
|
|
private AudioSource[] _sfxSources; // 재사용 풀
|
|
private int _nextIndex; // 라운드로빈 인덱스 (전부 재생 중일 때 가장 오래된 것 교체)
|
|
|
|
private void Awake()
|
|
{
|
|
// 싱글톤. 중복 생성되면 새로 들어온 쪽을 파괴.
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
Instance = this;
|
|
|
|
InitSfxPool();
|
|
}
|
|
|
|
public void OnSceneLoaded()
|
|
{
|
|
if(SceneManager.GetActiveScene().name == "StartScene")
|
|
{
|
|
bgmAudioSource.clip = StartSceneBgm;
|
|
}
|
|
|
|
if(SceneManager.GetActiveScene().name == "GameScene")
|
|
{
|
|
bgmAudioSource.clip = GameSceneBgm;
|
|
}
|
|
|
|
if(SceneManager.GetActiveScene().name == "BossScene")
|
|
{
|
|
bgmAudioSource.clip = BossSceneBgm;
|
|
}
|
|
|
|
bgmAudioSource.Play();
|
|
}
|
|
|
|
|
|
// SFX용 AudioSource를 미리 자식으로 생성. 재생 때마다 만들지 않고 재사용한다.
|
|
private void InitSfxPool()
|
|
{
|
|
_sfxSources = new AudioSource[sfxSourceCount];
|
|
for (int i = 0; i < sfxSourceCount; i++)
|
|
{
|
|
var go = new GameObject($"SfxSource_{i}");
|
|
go.transform.SetParent(transform, false);
|
|
|
|
var src = go.AddComponent<AudioSource>();
|
|
src.playOnAwake = false;
|
|
src.spatialBlend = 0f; // 2D 사운드 (위치 무시)
|
|
src.outputAudioMixerGroup = sfxGroup; // 믹서 SFX 그룹으로 라우팅
|
|
_sfxSources[i] = src;
|
|
}
|
|
}
|
|
|
|
// 효과음 재생. 풀에서 놀고 있는 AudioSource를 빌려 PlayOneShot.
|
|
public void PlaySfx(AudioClip clip, float volume = 1f)
|
|
{
|
|
if (clip == null || _sfxSources == null) return;
|
|
GetFreeSource().PlayOneShot(clip, volume);
|
|
}
|
|
|
|
// 재생 중이 아닌 소스를 우선 반환. 전부 사용 중이면 라운드로빈으로 가장 오래된 것 재사용.
|
|
private AudioSource GetFreeSource()
|
|
{
|
|
for (int i = 0; i < _sfxSources.Length; i++)
|
|
{
|
|
if (!_sfxSources[i].isPlaying)
|
|
return _sfxSources[i];
|
|
}
|
|
|
|
AudioSource src = _sfxSources[_nextIndex];
|
|
_nextIndex = (_nextIndex + 1) % _sfxSources.Length;
|
|
return src;
|
|
}
|
|
}
|