나 개발자 진짜 되냐?

[ 12月 27日 ] 오늘 내가 배운 것 _ 72日次 _ 크리스마스 주에도 사운드매니저를! 본문

유니티를 공부해봐요!

[ 12月 27日 ] 오늘 내가 배운 것 _ 72日次 _ 크리스마스 주에도 사운드매니저를!

Snow Rabbit 2024. 12. 27. 16:04

 

 

이렇게 쓰고 보니

나는 참 느리다는 생각이 들었다

무슨 사운드 매니저를 3일째 하고 있나...

싶긴 하다

 

어제는 마지막 모의면접 + 세션

등등으로 시간을 조금.. 썼다고 하면 핑계겠지..

ㅎㅋㅎㅋ

 

오늘은 진짜 왕 끝낼 것이다!

using System.Collections.Generic;
using UnityEngine;

public class SoundManager : Singleton<SoundManager>
{
    [SerializeField] private string audioSourcekey = "AudioSourcePrefab";
    [SerializeField] private int poolSize = 10; // 풀 크기

    private Queue<AudioSource> audioSourcePool = new Queue<AudioSource>();

    protected override void Start()
    {
        GameObject audioSourcePrefab = ResourceManager.Instance.LoadAsset<GameObject>(audioSourcekey, eAssetType.Prefab, eCategoryType.Sound);
        if(audioSourcePrefab == null)
        {
            return;
        }
        // 오디오 소스 풀 초기화
        for (int i = 0; i < poolSize; i++)
        {
            GameObject obj = Instantiate(audioSourcePrefab);
            AudioSource audioSource = obj.GetComponent<AudioSource>();
            obj.SetActive(false);
            audioSourcePool.Enqueue(audioSource);
        }
    }

    public void PlaySound(AudioClip clip, float volume = 1.0f, bool audioloop = false)
    {
        if (audioSourcePool.Count > 0)
        {
            // 풀에서 오디오 소스를 가져오기
            AudioSource audioSource = audioSourcePool.Dequeue();
            audioSource.gameObject.SetActive(true);
            

            // 효과음 설정 및 재생
            audioSource.clip = clip;
            audioSource.volume = volume;
            audioSource.loop = audioloop;
            audioSource.Play();

            // 재생 종료 후 반환
            StartCoroutine(ReturnToPool(audioSource));
        }
        else
        {
            Debug.LogWarning("AudioSource pool exhausted!");
        }
    }

    private System.Collections.IEnumerator ReturnToPool(AudioSource audioSource)
    {
        // Clip 재생 완료 대기
        yield return new WaitWhile(() => audioSource.isPlaying);

        // 풀에 반환
        audioSource.gameObject.SetActive(false);
        audioSourcePool.Enqueue(audioSource);
    }
}

이번에는 오브젝트 풀링으로 만들어보았다.

 

큐, 디큐를 사용했다.

 

문제는 오브젝트풀링을 진행하며 많은 부분이 이상해져 있었다.

 

1... 처음에 딕셔너리로 가져오던 방식이 사라졌다.

왜 없어졌지..

...

다 지우고 다시 해서 그렇지 뭐...

 

 

그래서 딕셔너리로 가져오는 방식으로 일단 합쳐봐야 한다.

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

public class SoundManager : Singleton<SoundManager>
{
    private Dictionary<string, AudioClip> soundList = new Dictionary<string, AudioClip>();
    private List<string> loadedSounds = new List<string>();

    private Queue<AudioSource> audioSourcePool = new Queue<AudioSource>();
    [SerializeField] private int poolSize = 10; // 풀 크기

    protected override void Awake()
    {
        base.Awake();

        for (int i = 0; i < poolSize; i++)
        {
            GameObject gameobj = new GameObject();
            gameobj.transform.setparent(transform);
            AudioSource audioSource = gameobj.AddComponent<AudioSource>();
            audioSource.gameObject.SetActive(false);
            audioSourcePool.Enqueue(audioSource);
        }
    }


    public AudioClip LoadSound(string soundName)
    {
        if(!soundList.TryGetValue(soundName, out AudioClip value))
        {
            AudioClip clip = ResourceManager.Instance.LoadAsset<AudioClip>(soundName, eAssetType.Sound);
            if (clip != null)
            {
                soundList.Add(soundName, clip);
            }
        }
        return soundList[soundName];
    }

    public void LoadSceneSounds(List<string> loadsound)
    {
        foreach (var sound in loadedSounds)
        {
            soundList.Remove(sound);
        }

        loadedSounds.Clear();

        foreach (var sound in loadsound)
        {
            LoadSound(sound);
            loadedSounds.Add(sound);
        }
    }

    public void UnloadSound(string soundName)
    {
        if (soundList.ContainsKey(soundName))
        {
            soundList.Remove(soundName);
        }
    }

    public void PlaySound(string soundName, float volume = 0.5f, bool loop = false)
    {
        AudioClip playAudio = LoadSound(soundName);
        if (playAudio == null) return;

        if (audioSourcePool.Count > 0)
        {
            AudioSource audioSource = audioSourcePool.Dequeue();
            audioSource.gameObject.SetActive(true);

            // 오디오 설정 및 재생
            audioSource.clip = playAudio;
            audioSource.volume = volume;
            audioSource.loop = loop;
            audioSource.Play();

            // 재생 종료 후 풀로 반환
            StartCoroutine(ReturnToPool(audioSource));
        }
    }

    private System.Collections.IEnumerator ReturnToPool(AudioSource audioSource)
    {
        yield return new WaitWhile(() => audioSource.isPlaying);

        audioSource.clip = null; // 클립 초기화
        audioSource.gameObject.SetActive(false);
        audioSourcePool.Enqueue(audioSource);
    }


}

이렇게 해주면

딕셔너리랑 오브젝트 풀이 합쳐졌다!

 

이렇게 해주니

한 오브젝트에 10개가 생겼어서

 

이렇게 하나 오브젝트를 만들어주고

거기에 추가해 주었다.

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

public class Sound : MonoBehaviour
{
    [SerializeField] private AudioClip startBGM;
    [SerializeField] private AudioClip sfx1;
    [SerializeField] private AudioClip sfx2;
    [SerializeField] private AudioClip sfx3;
    [SerializeField] private AudioClip sfx4;

    void Start()
    {
        SoundManager.Instance.PlaySound("Galaxy Blues_Loop", 0.1f, true);
    }

    public void OnButtonClick1()
    {
        // 버튼 클릭 효과음 재생
        SoundManager.Instance.PlaySound("yeah", 0.5f);
    }

    public void OnButtonClick2()
    {
        // 버튼 클릭 효과음 재생
        SoundManager.Instance.PlaySound("venom", 0.5f);
    }

    public void OnButtonClick3()
    {
        // 버튼 클릭 효과음 재생
        SoundManager.Instance.PlaySound("audioHS", 0.5f);
    }


    public void OnButtonClick4()
    {
        // 버튼 클릭 효과음 재생
        SoundManager.Instance.PlaySound("hello", 0.5f);

    }

    public void OnButtonClick5()
    {
        // 버튼 클릭 효과음 재생
        SoundManager.Instance.PlaySound("Sci-Fi_BGM#6", 0.5f);
    }
}

 

이렇게 해주고 사용하니

잘 시행되었다.

버튼 하나로 주르륵 실행되긴 하던데

이건 뭐 실험용으로 만든 거라 괜찮다!

 

프리팹이다보니

씬이 바뀔때마다 사라졌다가 생성되어서

오디오소스가 널이 되는 상황이 생긴다.

그래서!

Dondestroy에다가 매니저를 넣어놓고

그 오디오 매니저 밑에다가 만들어두면 파괴되지않는다!

gameobj.transform.setparent(transform);

내 자신을 부모밑으로 넣어준다. 라는 뜻

setparent

 

중요한건,

부모밑으로 넣어주려면 transform을 써야한다는것!