프로젝트/건즈앤 레이첼스

[유니티 프로젝트] 오디오 매니저 제작

Bueong_E 2023. 5. 16. 01:13
반응형
SMALL

https://assetstore.unity.com/packages/tools/audio/sound-manager-audio-sound-and-music-manager-for-unity-56087

 

Sound Manager - Audio, Sound and Music Manager for Unity | 음악 | Unity Asset Store

Get the Sound Manager - Audio, Sound and Music Manager for Unity package from Digital Ruby (Jeff Johnson) and speed up your game development process. Find this & other 음악 options on the Unity Asset Store.

assetstore.unity.com

 

 위의 사운드 매니저 스크립트를 활용하여 현재 제작중인 건즈 앤 레이첼스 프로젝트에 맞게 개량하였다.

 

우선 사운드 매니저 자체는 굉장히 심플한 편인데 글로벌 볼륨을 가지고 있고 해당 볼륨을 기반으로 오디오 소스 컴포넌트가 붙은 오브젝트를 자동 생성하여 하이어라키에서 자신을 숨긴다 이후 클래스 익스텐션과 확장 메서드를 이용하여 호출한 객체의 컴포넌트를 전달, 사용하는 것이 구현되어있고 기본적으로 두가지 분류 (음악, SFX) 두가지 를 재생하며 각각 루핑 기능을 지원한다.)

 

문제는 위의 스크립트는 접근자를 사용해 접근할수있는 메서드가 처음 보는 사람에겐 혼란스러울수 있고 직관적이지 않을수 있기 때문에 프로젝트에 맞는 싱글턴 오디오 매니저를 만들어 사용하였다.

 

우선 코드를 보자

using DigitalRuby.SoundManagerNamespace;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Android;
using static App;


public class AudioManager : MonoBehaviour
{
    public enum eBGMusicPlayList
    {
        NONE = -1,
        TITLEBG,
        SANTUARYBG,
        DUNGEONBG,
        DUNGEONBGBOSS,
    }

    /// <summary>
    /// 재생하고 싶은 음원의 명과 동일하게 설정
    /// </summary>
    public enum eSFXMusicPlayList
    {
        NONE = -1,
    }

    public static AudioManager instance;
    private AudioSource audioSource;  
    private List<AudioClip> BGAudioClipList;

    private const string path = "Sounds/{0}";

    private void Awake()
    {
        this.BGAudioClipList = new List<AudioClip>();
        instance = this;
        this.audioSource = this.GetComponent<AudioSource>();
        DontDestroyOnLoad(this.gameObject);
        SoundManager.MusicVolume = InfoManager.instance.settingInfo.musicVolume;
        SoundManager.SoundVolume = InfoManager.instance.settingInfo.sfxVolume;
    }

    public void BGMusicControl(eBGMusicPlayList musicTitle = default(eBGMusicPlayList), bool isStop = false)
    {      
        if (isStop)
        {
            SoundManagerExtensions.StopLoopingMusicManaged(this.audioSource);
        }
        else
        {
            Debug.LogFormat("{0} : 실행할 음원 클립 이름", BGAudioClipList.Count);
            var audioClip = this.BGAudioClipList.Find(x => x.name == musicTitle.ToString());
            this.audioSource.clip = audioClip;
            SoundManagerExtensions.PlayLoopingMusicManaged(this.audioSource, 1.0f, 3.0f, false);
        }
       
    }

    public void SceneBGMusicSetting(App.eSceneType sceneType)
    {
        Debug.Log("오디오 클립 준비");
        this.BGAudioClipList = null;
        string folderPath = string.Format(path, sceneType.ToString());
        AudioClip[] clips = Resources.LoadAll<AudioClip>(folderPath);
        this.BGAudioClipList = clips.ToList();         
    }


    /// <summary>
    /// 재생을 원하는 사운드 이펙트 이넘명을 넣으면 재생. (재생빈도가 잦은 음원들은 오디오 소스 없이 재생 추천)
    /// </summary>
    /// <param name="SFXSoundTitle">재생하고 싶은 사운드 이펙트</param>
    /// <param name="source">객체별 재생을 원한다면</param>
    public void SFXSoundPlay(eSFXMusicPlayList SFXSoundTitle , AudioSource source = null)
    {
        var audioClip = this.BGAudioClipList.Find(x => x.name == SFXSoundTitle.ToString());

        if (source == null)
        {
            SoundManagerExtensions.PlayOneShotSoundManaged(this.audioSource,audioClip);
        }
        else
        {
            SoundManagerExtensions.PlayOneShotSoundManaged(source, audioClip);
        }
    }

    public void Vibrate()
    {
        if (InfoManager.instance.settingInfo.isVive)     
            Handheld.Vibrate();        
    }
}

 

여기서 BG같은 경우 메인에서 아래와같이 재생 시켜주며 자동으로 다른 객체 (예를 들어 보스라던지) 등이 BG를 변경하면 페이드인 아웃 되며 부드럽게 음악이 시작된다.

 

 public void Init()
    {
        this.spawnPoint = GameObject.FindObjectOfType<SanctuaryPlayerSpawnPoint>();
        this.spawnPoint.Init();
        this.KightList = GameObject.FindObjectsOfType<KnightsController>().ToList();
        this.KightList.ForEach((x) => x.Init());
        this.portal = GameObject.FindObjectOfType<PortalController>();
        this.chestItemGenerator.Init();

        this.onStartPortalAnim = () =>{
            this.StartDungeonPortalAnim();
        };

        this.portal.onPlayerGoToThePortal = () =>{
            EventDispatcher.Instance.Dispatch<Action>(EventName.UIDialogPanelRandomWeaponDialog,this.onStartPortalAnim);
        };

        this.director.Init();
       
        this.StartCoroutine(this.CoInitPlayerSpawn()); 
        
        EventDispatcher.Instance.AddListener(EventName.SanctuarySceneMainIntotheDungeon,this.onintotheDungeon);
        AudioManager.instance.BGMusicControl(AudioManager.eBGMusicPlayList.SANTUARYBG); // BG 재생
    }

 

 

또한 음악이 아닌 단순 SFX 를 원샷으로 재생하고 싶다면 아래와 같이 사용하면 된다.

 

 private void Update()
    {
        if (Input.GetKeyDown(KeyCode.K))
        {
            var AS = this.GetComponent<AudioSource>();
            AudioManager.instance.SFXSoundPlay(eSFXMusicPlayList.NONE,AS);
        }
    }

에시를 위해 업데이트 메서드에 구현 , 재생 객체의 오디오 소스 컴포넌트를 함께 넘겨주면 된다.

 

음원은 리소스 폴더에 각 씬 몇칭으로 저장하며 각 씬이 로드될시 각각의 씬에서 필요한 음원만을 불러오는 식으로 구현하였다.

 

이는 오디오를 재생하는 객체가 음원을 따로 가지고 있지 않아도 되며 단순히 어떤 음원을 사용할지 이름만 정의해두고 알고 있으면 되는것.

 

+ 진동 기능도 구현 전역 설정에 맞게   Handheld.Vibrate();   메서드를 사용하여 진동기능 ON OFF 여부에 따라 진동을 발생시킨다. (IOS 의 경우 다른 메서드를 사용하는 것으로 알고 있는데 이는 따로 IOS 빌드 편에서 다루겠다.)

반응형
LIST