스파르타코딩클럽 게임개발

오늘은 스파르타 코딩 클럽 unity 게임 개발 과정 48일차(간단한 사운드 매니저)

코드천자문 2024. 1. 9. 09:14
반응형

SoundManager 클래스

SoundManager 클래스 개요

Unity 프로젝트에서 배경음악과 효과음을 관리하기 위해 설계된 SoundManager 클래스

이 클래스는 싱글톤 패턴을 사용하여 프로젝트 어디에서든 접근 가능하고, 음악과 효과음을 별도로 관리한다.

SoundManager.cs

using System;
using System.Collections.Generic;
using UnityEngine;

public enum SoundType
{
    HIT,
    DEAD,
    //TODO..
}

public class SoundManager : MonoBehaviour
{
    private Dictionary<string, AudioSource> musicSources = new Dictionary<string, AudioSource>();
    private Dictionary<string, AudioSource> effectSources = new Dictionary<string, AudioSource>();

    private bool isMusicMuted = false;
    private bool isEffectsMuted = false;

    private static SoundManager _instance;
    public static SoundManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<SoundManager>();
            }
            return _instance;
        }
    }

    // 배경음악 재생
    public void PlayMusic(SoundType key, bool loop = true)
    {
        Debug.Log(gameObject);
        if (!musicSources.TryGetValue(Enum.GetName(typeof(SoundType), key), out AudioSource musicSource))
        {
            Main.Resource.LoadAsync<AudioClip>(Enum.GetName(typeof(SoundType), key), clip =>
            {
                if (clip != null)
                {
                    musicSource = GetOrCreateAudioSource(musicSources, Enum.GetName(typeof(SoundType), key), loop);
                    musicSource.clip = clip;
                    musicSource.Play();
                }
                else
                {
                    Debug.LogError("로드하지 못함 : " + Enum.GetName(typeof(SoundType), key));
                }
            });
        }
        else
        {
            if (!musicSource.isPlaying)
            {
                musicSource.Play();
            }
        }
    }

    // 효과음 재생
    public void PlayEffect(SoundType key)
    {
        if (!effectSources.TryGetValue(Enum.GetName(typeof(SoundType), key), out AudioSource effectSource))
        {
            Main.Resource.LoadAsync<AudioClip>(Enum.GetName(typeof(SoundType), key), clip =>
            {
                if (clip != null)
                {
                    effectSource = GetOrCreateAudioSource(effectSources, Enum.GetName(typeof(SoundType), key), false);
                    effectSource.clip = clip;
                    effectSource.PlayOneShot(clip);
                }
                else
                {
                    Debug.LogError("로드하지 못함 : " + Enum.GetName(typeof(SoundType), key));
                }
            });
        }
        else
        {
            effectSource.PlayOneShot(effectSource.clip);
        }
    }

    private AudioSource GetOrCreateAudioSource(Dictionary<string, AudioSource> sources, string key, bool loop)
    {
        if (!sources.TryGetValue(key, out AudioSource source))
        {
            source = gameObject.AddComponent<AudioSource>();
            source.loop = loop;
            sources[key] = source;
        }
        return sources[key];
    }

}

주요 기능과 메서드 설명

1. 싱글톤 패턴 (Singleton Pattern)

private static SoundManager _instance;
public static SoundManager Instance
{
    get
    {
        if (_instance == null)
        {
            _instance = FindObjectOfType<SoundManager>();
        }
        return _instance;
    }
}
  • SoundManager는 싱글톤 패턴으로 구현되어 있다. 이를 통해 하나의 인스턴스만 유지되며, Instance 프로퍼티를 통해 접근할 수 있다.
  • 인스턴스가 없을 경우 FindObjectOfType 메서드로 찾아 생성한다.

2. 배경음악 재생 (PlayMusic)

 public void PlayMusic(SoundType key, bool loop = true)
    {
        Debug.Log(gameObject);
        if (!musicSources.TryGetValue(Enum.GetName(typeof(SoundType), key), out AudioSource musicSource))
        {
            Main.Resource.LoadAsync<AudioClip>(Enum.GetName(typeof(SoundType), key), clip =>
            {
                if (clip != null)
                {
                    musicSource = GetOrCreateAudioSource(musicSources, Enum.GetName(typeof(SoundType), key), loop);
                    musicSource.clip = clip;
                    musicSource.Play();
                }
                else
                {
                    Debug.LogError("로드하지 못함 : " + Enum.GetName(typeof(SoundType), key));
                }
            });
        }
        else
        {
            if (!musicSource.isPlaying)
            {
                musicSource.Play();
            }
        }
    }
  • PlayMusic 메서드는 SoundType을 인자로 받아 해당하는 배경음악을 재생한다.
  • musicSources 딕셔너리를 사용하여 음악을 관리하며, 이미 로드된 음악은 즉시 재생되고, 그렇지 않은 경우 비동기로 로드한다.
  • loop 파라미터는 음악이 반복 재생될지 여부를 결정한다.

3. 효과음 재생 (PlayEffect)

public void PlayEffect(SoundType key)
    {
        if (!effectSources.TryGetValue(Enum.GetName(typeof(SoundType), key), out AudioSource effectSource))
        {
            Main.Resource.LoadAsync<AudioClip>(Enum.GetName(typeof(SoundType), key), clip =>
            {
                if (clip != null)
                {
                    effectSource = GetOrCreateAudioSource(effectSources, Enum.GetName(typeof(SoundType), key), false);
                    effectSource.clip = clip;
                    effectSource.PlayOneShot(clip);
                }
                else
                {
                    Debug.LogError("로드하지 못함 : " + Enum.GetName(typeof(SoundType), key));
                }
            });
        }
        else
        {
            effectSource.PlayOneShot(effectSource.clip);
        }
    }
  • PlayEffectSoundType을 인자로 받아 해당하는 효과음을 재생한다.
  • effectSources 딕셔너리를 통해 효과음을 관리하며, 로드되지 않은 경우 비동기로 로드하여 PlayOneShot 메서드로 재생한다.
  • PlayOneShot()은 단 한번만 재생한다는 뜻이다.

4. 오디오 소스 생성 및 관리 (GetOrCreateAudioSource)

 private AudioSource GetOrCreateAudioSource(Dictionary<string, AudioSource> sources, string key, bool loop)
    {
        if (!sources.TryGetValue(key, out AudioSource source))
        {
            source = gameObject.AddComponent<AudioSource>();
            source.loop = loop;
            sources[key] = source;
        }
        return sources[key];
    }
  • GetOrCreateAudioSource 메서드는 주어진 key에 맞는 AudioSource를 찾거나 새로 생성한다.
  • 이 메서드는 배경음악과 효과음 관리에 모두 사용되며, 필요한 경우 새로운 AudioSource 컴포넌트를 추가하여 생성한다.

5.예시

SoundManager.Instance.PlayMusic(SoundType.MUSIC_LEVEL1);
SoundManager.Instance.PlayEffect(SoundType.HIT);
SoundManager.Instance.PlayEffect(SoundType.DEAD);
반응형