강의, 책/[Unity] C#과 유니티로 만드는 MMORPG 게임 개발 시리즈

Section 9. Sound - Sound Manager(1)

hye3193 2024. 2. 2. 17:43
AudioSource audio = GetComponent<AudioSource>();
audio.PlayOneShot(audioClip);
audio.PlayOneShot(audioClip2);

PlayOneShot 함수: clip을 한번 재생시킨다(여러 개 겹쳐서 실행시키면 그대로 겹쳐서 재생시킴)

* 만약 audio clip이 재생되고 있는 중에 해당 클립을 들고 있는 게임 오브젝트가 destroy된다면 중간에 사운드가 끊기게 된다 -> 클립을 게임 오브젝트가 들고 있는 게 아니라, manager가 관리하게 만든다

 

Assets > Scripts > Utils > Define.cs에 Sound 열거체를 추가해준다

public enum Sound
{
    Bgm,
    Effect,
    MaxCount // 열거체 내 오브젝트의 개수 파악을 위함
}

 

Sound 리소스들을 모아둘 폴더(Assets > Resources > Sounds)를 만들어준다

 

Assets > Scripts > Managers > SoundManager.cs를 생성해주고

public class SoundManager
{
    public void Init()
    {
        GameObject go = GameObject.Find("@Sound");
        if (go == null)
        {
            go = new GameObject { name = "@Sound" };
            Object.DontDestroyOnLoad(go);
            
            string[] soundNames = System.Enum.GetNames(typeof(Define.Sound));
            for (int i = 0; i < soundNames.Length - 1; i++)
            {
                GameObject go = new GameObject { name = soundNames[i] };
                _audioSources[i] = go.AddComponent<AudioSource>();
                go.transform.parent = root.transform;
            }
            
            _audioSources[(int)Define.Sound.Bgm].loop = true;
        }
    }
    
    // MaxCount 개수만큼 audioSources 생성
    AudioSource[] _audioSources = new AudioSource[(int)Define.Sound.MaxCount];
    
    public void Play(string path, Define.Sound type = Define.Sound.Effect, float pitch = 1.0f)
    {
        // 경로에 Sounds가 없을 경우 자동으로 추가
        if (path.Contains("Sounds/") == false)
            path = $"Sounds/{path}";
        
        if (type == Define.Sound.Bgm)
        {
            AudioClip audioClip = Managers.Resource.Load<AudioClip>(path);
            if (audioClip == null)
            {
                Debug.Log($"AudioClip Missing : {path}");
                return;
            }
            
            AudioSource audioSource = _audioSources[(int)Define.Sound.Bgm];
            // 이전에 재생 중인 bgm 있을 경우 중지시키고 시작
            if (audioSource.isPlaying)
                audioSource.Stop();
            
            audioSource.pitch = pitch;
            audioSource.clip = audioclip;
            audioSource.Play();
        }
        else
        {
            AudioClip audioClip = Managers.Resource.Load<AudioClip>(path);
            if (audioClip == null)
            {
                Debug.Log($"AudioClip Missing : {path}");
                return;
            }
            
            AudioSource audioSource = _audioSources[(int)Define.Sound.Effect];
            audioSource.pitch = pitch;
            audioSource.clip = audioClip;
            audioSource.PlayOneShot(audioClip);
        }
    }
}

* Rect transform의 경우 부모를 지정하기 위해 setParent 사용하나, 일반적인 경우 그냥 {object}.transform.parent = {parent}.transform; 해주면 된다

 

Managers.cs에 연결해주고, 싱글톤 패턴 내에 sound manager를 낑겨서 같이 초기화시켜준다

SoundManager _sound = new SoundManager();

public static SoundManager Sound { get { return Instance._sound; } }

static void Init()
{
    if (s_instance == null)
    {
        GameObject go = GameObject.Find("@Managers");
        if (go == null)
        {
            go = new GameObject { name = "@Managers" };
            go.AddComponent<Managers>();
        }
        
        DontDestroyOnLoad(go);
        s_instance = go.GetComponent<Managers>();
        
        // sound manager 초기화
        s_instance._sound.Init();
    }
}

 

 

사용

Managers.Sound.Play(Define.Sound.Effect, "path");