내일배움캠프/Unity Final Projcet

[Untiy] AudioMixer 기반의 BGM & SFX 사운드 매니저 제작하기

danpat77 2025. 4. 22. 20:33

이번에는 사운드를 체계적으로 관리하기 위해
AudioMixer를 기반으로 한 BGM / SFX 분리형 사운드 매니저를 제작해봤습니다.

슬라이더로 실시간 볼륨 조절도 가능하고,버튼으로 음소거/해제 시 아이콘이 바뀌는 기능까지 구현했습니다.


구현 목표 및 개요

 

  • BGM과 SFX를 AudioMixer를 통해 개별 제어
  • 슬라이더로 실시간 볼륨 조절
  • 음소거 버튼 클릭 시 아이콘 변경
  • 씬 전환에도 BGM 유지
  • 슬라이더 값 0일 경우에도 자동으로 음소거 아이콘 반영

1. AudioMixer 설정

  1. MainMixer 생성
    Assets > Create > Audio > Audio Mixer
  2. Group 분리
    Master 하위에 BGM, SFX 그룹 생성
  3. Volume 파라미터 Expose
    각 그룹의 Volume 슬라이더 → 우클릭 → Expose to script
    • 이름: BGMVolume, SFXVolume
  4. AudioSource 연결
    오디오 출력용 AudioSource 2개 생성 후 각각 Output에 BGM / SFX 연결

2.구현된 기능

2-1. 슬라이더 볼륨 조절

Mathf.Log10(volume) * 20을 통해 AudioMixer가 기대하는 dB 기준으로 정확한 제어

2-2. 음소거 버튼

음소거 버튼 클릭 시 -80dB 설정, 다시 누르면 이전 볼륨 복원

2-3. 아이콘 자동 전환

  • 음소거 상태이면 🔇
  • 슬라이더 값 0일 경우도 🔇
  • 음량이 살아 있으면 🔊

2-4. 씬 전환 후에도 유지

DontDestroyOnLoad() 적용으로 BGM 유지


3. 핵심 코드 정리

3-1. 사운드 타입 enum 정의

public enum BGMType
{
    Main,
    Battle,
    // 필요시 확장 가능
}

public enum SFXType
{
    ButtonClick,
    Gacha,
    TurretShoot,
    Explosion,
    EnemyDie
}
  • BGMType과 SFXType으로 사운드 종류를 구분합니다.
  • 이후 코드에서 PlayBGM(BGMType.Main)처럼 사용하면, 오타 없이 안전하게 사운드를 관리할 수 있습니다.

3-2. SoundManager.cs (요약본)

public class SoundManager : Singleton<SoundManager>
{
    [SerializeField] private AudioSource bgmSource;
    [SerializeField] private AudioSource sfxSource;
    [SerializeField] private AudioMixer audioMixer;

    private float lastBgmVolume = 0.8f;
    private float lastSfxVolume = 0.8f;
    private bool isBgmMuted = false;
    private bool isSfxMuted = false;

    public bool IsBGMMuted => isBgmMuted;
    public bool IsSFXMuted => isSfxMuted;

    private Dictionary<BGMType, AudioClip> bgmDict = new();
    private Dictionary<SFXType, AudioClip> sfxDict = new();

    public void PlayBGM(BGMType type, bool loop = true)
    {
        if (bgmDict.TryGetValue(type, out var clip))
        {
            bgmSource.clip = clip;
            bgmSource.loop = loop;
            bgmSource.Play();
        }
    }

    public void PlaySFX(SFXType type)
    {
        if (sfxDict.TryGetValue(type, out var clip))
            sfxSource.PlayOneShot(clip);
    }
}

 

  • Dictionary<BGMType, AudioClip> 구조로 관리되기 때문에, 사운드 키의 충돌이나 중복 위험 없이 효율적으로 접근할 수 있습니다.
  • enum을 쓰면 코드 자동완성도 지원되기 때문에, 관리가 매우 편리해집니다.

3-3. UI 연동 예시 - SoundController.cs

private void UpdateIcon(Image icon, float volume, bool isMuted)
{
    bool isEffectivelyMuted = isMuted || volume <= 0.0001f;
    icon.sprite = isEffectivelyMuted ? iconSoundOff : iconSoundOn;
}

 

  • 슬라이더 값이 0이 되거나 음소거 상태일 경우 자동으로 아이콘 변경
  • UI와 논리 상태를 명확히 연결해주는 역할을 합니다

4. 적용 화면 예시

 

 

  • 슬라이더를 조절하면서 소리가 즉시 반응
  • 버튼 클릭으로 음소거 및 복구
  • 음소거 상태에 따라 아이콘도 자동 전환

마무리

번 작업에서는 단순히 소리를 내는 기능을 넘어서,
볼륨 상태 관리, UI 반응, 재생 상태 유지
게임 전반에서 필요한 사운드 구조를 체계적으로 구성해볼 수 있었습니다.

특히 SoundManager와 SoundController의 역할을 분리하면서
UI와 로직의 책임을 나누는 연습도 되었습니다.

앞으로도 이 구조를 기반으로 씬별 BGM 전환, 페이드 효과, 스테이지 클리어 시 효과음 재생 등으로 확장할 수 있을 것 같아 기대가 됩니다.