본문 바로가기
Development/Internship

[멋사 로켓단 인턴쉽] 7일차 - Audio Manager 완성

by Mobics 2025. 8. 14.

목차


    멋쟁이사자처럼 로켓단 인턴쉽

    25.08.14

    회의록

    >> 안건

    • 업무 업데이트
      • 질문 혹은 피드백 요청
    • 주요 안건
      • 1회차 완전플레이 개발 지속
      • 1차 요소 완료 후 부족한 사항 피드백
    • 향후 마일스톤
      • 완전 완성

     

    >> 회의 내용

    • 1회차 완전 플레이 마무리 단계
    • 개발 속도 가속을 위해 완전 완성에 필요한 기능과 연출을 브레인스토밍하여 마일스톤 작성.
    • 완전 완성을 목표로 개발 시작.

     

    Audio Manager 완성

    : 지난 시간에 이어 Audio Manager를 만들어서 완성했다.

     

    >> 만드려고 하는 Manager 구조

    • 어디서든 AudioManager를 Instance로 호출해서 BGM 또는 SFX를 재생할 수 있도록
    • Audio Toggle을 눌렀을 때 BGM과 SFX 모두 켜지거나 꺼지도록
    • AudioManager는 각 Controller를 조율만 하고, 재생이나 정지 등의 세부 로직은 각 Controller들이 담당하도록
    • 새로운 BGM와 SFX를 추가할 때 간단히 추가할 수 있도록 --> 추가할 Audio를 Inspector에서 바인딩, Controller에서 재생 함수 추가, 사용할 곳에서 AudioManager를 호출하여 바로 사용

     

    >> 구현 방법

    1. 어디서든 AudioManager를 Instance로 호출해서 BGM 또는 SFX를 재생할 수 있도록

    : AudioManager를 Singleton 패턴으로 만들어서 구현

     

    2. Audio Toggle을 눌렀을 때 BGM과 SFX 모두 켜지거나 꺼지도록

    : AudioManager에 현재 Audio Toggle이 On인지 Off인지를 구분하는 bool값을 추가하여 bool값에 따라 각 Manager를 통해 BGM과 SFX를 켜거나 끄도록 구현

     

    3. AudioManager는 각 Controller를 조율만 하고, 재생이나 정지 등의 세부 로직은 각 Controller들이 담당하도록

    : 각 Controller는 AudioManager를 통해 접근하도록 하고 BGM과 SFX 관련한 작업은 각 Controller에서 실행되도록 구현

     

    4. 새로운 BGM와 SFX를 추가할 때 간단히 추가할 수 있도록 --> 추가할 Audio를 Inspector에서 바인딩, Controller에서 재생 함수 추가, 사용할 곳에서 AudioManager를 호출하여 바로 사용

    : 각 Controller에서 추가할 Audio를 바인딩 받을 수 있도록 SerializeField를 사용하고, 재생 함수를 public으로 작성하여 어디서든 AudioManager를 호출하고 AudioManager를 통해 Controller에 접근하여 사용하도록 구현

     

    >> 작성한 코드

    1. AudioManager.cs

    <hide/>
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class AudioManager : Singleton<AudioManager>
    {
        [SerializeField] private BGMController bgmController;
        [SerializeField] private SFXController sfxController;
        
        public BGMController BGM => bgmController;
        public SFXController SFX => sfxController;
    
        private bool _isAudioOn = true;     // Audio 토글이 On인지, Off인지
    
        protected override void Initialize()
        {
            base.Initialize();
            _isAudioOn = true;   // 기본값은 켜짐으로 설정
            
            // 필요 시, 초기화    ex) 저장된 설정 로드
        }
        
        public void SetBGMController(BGMController bgmController)
        {
            this.bgmController = bgmController;
        }
        
        public void SetSFXController(SFXController sfxController)
        {
            this.sfxController = sfxController;
        }
    
        // Audio 토글을 통해 BGM 및 SFX On/Off
        public void ToggleAudio()
        {
            _isAudioOn = !_isAudioOn;
            bgmController.SetBGMOn(_isAudioOn);
            sfxController.SetSFXOn(_isAudioOn);
        }
    }

     

    2. BGMController.cs

    <hide/>
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    using static Constants;
    
    public class BGMController : Singleton<BGMController>
    {
        // BGM을 추가하실 때, 여기에 추가해주세요.
        [SerializeField] private AudioClip titleBGM;
        [SerializeField] private AudioClip gameBGM;
        
        // 여기까지
        
        private AudioSource _bgmSource;
        private AudioClip _currentBGM;     // 현재 재생해야 할 BGM 저장
        private bool _isBGMOn = true;       // BGM이 켜져있는지 여부
        public bool IsBGMOn() => _isBGMOn;
    
        protected override void Initialize()
        {
            SceneManager.sceneLoaded += OnSceneLoaded;
            _bgmSource = gameObject.AddComponent<AudioSource>();
        }
    
        private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
        {
            //SceneManager.sceneLoaded -= OnSceneLoaded;
            AudioManager.Instance.SetBGMController(this);
            
            // Scene 이름에 맞게 BGM 재생
            // TODO: 유저 정보에 소리 설정이 OFF라면 재생되지 않도록
            switch (scene.name)
            {
                case TitleSceneName:
                    PlayTitleBGM();
                    break;
                case GameSceneName:
                    PlayGameBGM();
                    break;
                default:
                    StopBGM();
                    break;
            }
        }
    
        // BGM를 추가하신 뒤, 아래 함수 모음에 재생 함수를 작성해주세요. 그리고 작성하신 함수를 통해 사용하시면 됩니다.
        #region PlayBGM 함수 모음 
    
        public void PlayTitleBGM() => PlayBGM(titleBGM);
    
        public void PlayGameBGM() => PlayBGM(gameBGM);
    
        #endregion
    
        // BGM 재생 (반복 O)
        private void PlayBGM(AudioClip clip)
        {
            _currentBGM = clip;     // 현재 BGM 저장
            if (!_isBGMOn || clip == null) return;
    
            _bgmSource.clip = clip;
            _bgmSource.loop = true;
            _bgmSource.Play();
        }
    
        // BGM 중지
        private void StopBGM()
        {
            if (_bgmSource != null)
            {
                _bgmSource.Stop();
            }
        }
    
        // _isBGMOn값을 조정하고 그에 따라 BGM 재생 및 중지
        public void SetBGMOn(bool isBGMOn)
        {
            _isBGMOn = isBGMOn;
            if (_isBGMOn && _currentBGM != null)   // 재생
            {
                PlayBGM(_currentBGM);
            }
            else   // 중지
            {
                StopBGM();
            }
        }
    }

     

    3. SFXController.cs

    <hide/>
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class SFXController : Singleton<SFXController>
    {
        // SFX를 추가하실 때 여기에 추가해주세요.
        [SerializeField] private AudioClip buttonClick;
        [SerializeField] private AudioClip stamp;
        
        // 여기까지
    
        private AudioSource _sfxSource;
        private bool _isSFXOn = true;       // SFX가 켜져있는지 여부
        public bool IsSFXOn() => _isSFXOn;
        
        protected override void Initialize()
        {
            SceneManager.sceneLoaded += OnSceneLoaded;
            _sfxSource = gameObject.AddComponent<AudioSource>();
        }
    
        private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
        {
            //SceneManager.sceneLoaded -= OnSceneLoaded;
            AudioManager.Instance.SetSFXController(this);
        }
    
        // SFX를 추가하신 뒤, 아래 함수 모음에 재생 함수를 작성해주세요. 그리고 작성하신 함수를 통해 사용하시면 됩니다.
        #region PlaySFX 함수 모음
    
        public void PlayButtonClick() => PlaySFX(buttonClick);
    
        public void PlayStamp() => PlaySFX(stamp);
    
        #endregion
    
        // SFX 1번 재생
        private void PlaySFX(AudioClip clip)
        {
            if (!_isSFXOn || clip == null) return;
            _sfxSource.PlayOneShot(clip);
        }
    
        // _isSFXOn 조정
        public void SetSFXOn(bool isSFXOn)
        {
            _isSFXOn = isSFXOn;
        }
    }