포스트

섹션9. Sound

위 글은 인프런에 있는 Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진 강의를 듣고 남긴 필기입니다.

[사운드를 들을 때 필요한 것]

  • 소리의 근원지 (음향 송신) : AudioSource
  • 소리 : AudioClip
  • 귀 (음향 수신) : AudioListener → 기본 MainCamera에 부착되어 있음.

AudioSource 컴포넌트

Untitled (10)

SoundManager

  • Sound를 담당하는 SoundManager를 만듦.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
public class SoundManager
{
    private AudioSource[] _audioSources = new AudioSource[(int)Define.Sound.MaxCount];
    // AudioClip Caching을 담당하는 Dictionary
    private Dictionary<string, AudioClip> _audioClips = new Dictionary<string, AudioClip>();
    
    // [사운드를 들을 때 필요한 것]
    // 소리의 근원지 (음향 송신) : AudioSource
    // 소리                   : AudioClip
    // 귀 (음향 수신)          : AudioListener

    public void Init()
    {
        GameObject root = GameObject.Find("@Sound");
        if (root == null)
        {
            root = new GameObject { name = "@Sound" };
            Object.DontDestroyOnLoad(root);

            string[] soundNames = System.Enum.GetNames(typeof(Define.Sound));
            for (int i = 0; i < soundNames.Length - 1; i++)     // Define.Sound.MaxCount는 제외
            {
                GameObject go = new GameObject { name = soundNames[i] };
                _audioSources[i] = go.AddComponent<AudioSource>();
                go.transform.parent = root.transform;
            }

            _audioSources[(int)Define.Sound.Bgm].loop = true;       // BGM은 Loop : true
        }
    }
    
    /// <summary>
    /// 오디오 플레이 함수. string 버전
    /// </summary>
    /// <param name="path">음원 파일 경로</param>
    /// <param name="type">어떤 형태의 음원인지</param>
    /// <param name="pitch"></param>
    public void Play(string path, Define.Sound type = Define.Sound.Effect, float pitch = 1.0f)
    {
        var audioClip = GetOrAddAudioClip(path, type);
        Play(audioClip, type,pitch);
    }

    /// <summary>
    /// 오디오 플레이 함수. AudioClip 버전
    /// </summary>
    /// <param name="audioClip">음원 AudioClip</param>
    /// <param name="type">어떤 형태의 음원인지</param>
    /// <param name="pitch"></param>
    public void Play(AudioClip audioClip, Define.Sound type = Define.Sound.Effect, float pitch = 1.0f)
    {
        if (audioClip == null)
            return;
        
        if (type == Define.Sound.Bgm)
        {
            AudioSource audioSource = _audioSources[(int)Define.Sound.Bgm];
            
            if(audioSource.isPlaying)
                audioSource.Stop();
            
            audioSource.pitch = pitch;
            audioSource.clip = audioClip;
            audioSource.Play();
        }
        else
        {
            AudioSource audioSource = _audioSources[(int)Define.Sound.Effect];
            audioSource.pitch = pitch;
            audioSource.PlayOneShot(audioClip);
        }
    }

    /// <summary>
    ///  AudioClip을 불러올 때 활용. AudioClip Caching 함수.
    /// </summary>
    /// <param name="path">AudioClip 파일 경로</param>
    /// <returns></returns>
    AudioClip GetOrAddAudioClip(string path, Define.Sound type = Define.Sound.Effect)
    {
        if (path.Contains("Sounds/") == false)
            path = $"Sounds/{path}";
        
        AudioClip audioClip = null;
        
        if (type == Define.Sound.Bgm)       // BGM일 때
        {
            audioClip = Managers.Resource.Load<AudioClip>(path);
        }
        else                                // Effect일 때
        {
            if (_audioClips.TryGetValue(path, out audioClip) == false)      // 조건부  Caching
            {
                audioClip = Managers.Resource.Load<AudioClip>(path);
                _audioClips.Add(path,audioClip);
            }
        }
        
        if (audioClip == null)
            Debug.Log($"AudioClip is Missing! {path}");

        return audioClip;
    }

    /// <summary>
    /// AudioClip Cache Clear 함수.
    /// </summary>
    public void Clear()
    {
        foreach (var audioSource in _audioSources)
        {
            audioSource.clip = null;
            audioSource.Stop();
        }
        _audioClips.Clear();
    }
}
  • Sound의 종류를 구분하기 위해 Utils > Define.cs 에 다음과 같은 enum을 생성
1
2
3
4
5
6
public enum Sound
{
    Bgm,
    Effect,
    MaxCount,
}
  • Managers 클래스에 다음의 함수를 추가
1
2
3
4
5
6
7
8
9
10
/// <summary>
/// Scene을 이동할 때 호출해야 하는 함수.
/// </summary>
public static void Clear()
{
    Sound.Clear();    // Caching된 AudioClip들을 비우는 함수
    Input.Clear();    // KeyAction과 MouseAction을 비우는 함수
    UI.Clear();       // 모든 Popup과 SceneUI를 비우는 함수
    Scene.Clear();    // 현재 Scene클래스(BaseScene을 상속하는 클래스)의 Clear()를 호출하는 함수
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.