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(); 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; } }