본문 바로가기

Unity_C#/Unity

[Unity/C#] Pooling시 Audio 관리

반응형
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SoundManager : MonoBehaviour
{

    private Dictionary<string, float> audioVolume = new Dictionary<string, float>();
    private Dictionary<string, AudioClip> clipPool = new Dictionary<string, AudioClip>();

    private float mainVolume = 1;

    private List<SoundObject> soundObjectPool = new List<SoundObject>();

    private Transform poolParent = null;

    private bool isInit = false;
    private static SoundManager _current;
    public static SoundManager current
    {
        get
        {
            if (_current == null)
            {
                _current = new GameObject("SoundManager").AddComponent<SoundManager>();
                DontDestroyOnLoad(_current.gameObject);
                return _current;
            }
            else
                return _current;
        }
    }

    private void Awake()
    {
        Init();
    }

    private void Init()
    {
        this.audioVolume.Add("FX", 1 * this.mainVolume);
        this.audioVolume.Add("BGM", 1 * this.mainVolume);

        this.poolParent = new GameObject("SoundObject_PoolParent").transform;
        this.poolParent.SetParent(this.transform);
        this.poolParent.position = Vector3.zero;
        this.poolParent.localRotation = Quaternion.identity;
        this.poolParent.localScale = Vector3.one;
    }


    private SoundObject GetPoolingSoundObject()
    {
        for (int i = 0; i < this.soundObjectPool.Count; i++)
            if (!this.soundObjectPool[i].gameObject.activeSelf)
            {
                this.soundObjectPool[i].transform.SetParent(null);
                this.soundObjectPool[i].transform.position = Vector3.zero;
                this.soundObjectPool[i].transform.localScale = Vector3.one;
                this.soundObjectPool[i].transform.localRotation = Quaternion.identity;
                this.soundObjectPool[i].gameObject.SetActive(true);
                return this.soundObjectPool[i];
            }

        return null;
    }

    private AudioClip GetPoolingAudioClip(string path)
    {
        if (this.clipPool.ContainsKey(path))
            return this.clipPool[path];
        else
        {
            AudioClip clip = Resources.Load<AudioClip>(path);

            if (clip != null)
            {
                this.clipPool[path] = clip;
                return this.clipPool[path];
            }
            else
            {
                Debug.LogWarning("존재 하지 않는 오디오 경로 입니다.");
                return null;
            }
        }
    }

    private SoundObject CreateSoundObject()
    {
        var soundObject = Instantiate(Resources.Load<SoundObject>("Sound/SoundObject"));
        soundObject.transform.position = Vector3.zero;
        soundObject.transform.localScale = Vector3.one;
        soundObject.transform.localRotation = Quaternion.identity;

        this.soundObjectPool.Add(soundObject);
        return soundObject;
    }

    private SoundObject GetSoundObject(float volume, Vector3 soundPos)
    {
        var soundObject = GetPoolingSoundObject();
        if (soundObject == null)
            soundObject = CreateSoundObject();

        soundObject.transform.position = soundPos;

        return soundObject;
    }

    public SoundObject PlayFXSound(AudioClip clip, float volume, Vector3 soundPos)
    {
        var soundObject = GetSoundObject(volume * this.audioVolume["FX"], soundPos);
        soundObject.PlayAudioOneShot(this, clip, volume);
        return soundObject;
    }

    public SoundObject PlayBGMSound(AudioClip clip, float volume, Vector3 soundPos)
    {
        var soundObject = GetSoundObject(volume * this.audioVolume["FX"], soundPos);
        soundObject.PlayAudioLoop(this, clip, volume);
        return soundObject;
    }

    public SoundObject PlayFXSound(string audioPath, float volume, Vector3 soundPos)
    {
        var soundObject = GetSoundObject(volume * this.audioVolume["FX"], soundPos);
        AudioClip clip = GetPoolingAudioClip(audioPath);
        soundObject.PlayAudioOneShot(this, clip, volume);
        return soundObject;
    }

    public SoundObject PlayBGMSound(string audioPath, float volume, Vector3 soundPos)
    {
        var soundObject = GetSoundObject(volume * this.audioVolume["FX"], soundPos);
        AudioClip clip = GetPoolingAudioClip(audioPath);
        soundObject.PlayAudioLoop(this, clip, volume);
        return soundObject;
    }

    public void ReturnPool(SoundObject soundObject)
    {
        soundObject.transform.SetParent(this.poolParent);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cube : MonoBehaviour
{
    public AudioClip bulletSound = null;

    private void Start()
    {
        //CreateSoundObject();
        SoundManager.current.PlayFXSound(bulletSound, 1, this.transform.position);

    }

    private void CreateSoundObject()
    {
        //게임 오브젝트 생성 (사운드 오브젝트)
        GameObject soundObject = new GameObject("SoundObject");
        
        //생성된 사운드 오브젝트를 자식으로... -> 총알이 멀어지면 소리도 함께 멀어져야하니까
        soundObject.transform.SetParent(this.transform);

        //사운드 포지션, 로테이션 (0, 0, 0)으로 초기화
        soundObject.transform.localPosition = Vector3.zero;
        soundObject.transform.localRotation = Quaternion.identity;

        //사운드 오브젝트에 AudioSource 컴포넌트 붙이기
        AudioSource source = soundObject.AddComponent<AudioSource>();

        //사운드 오브젝트 클립 연결
        source.clip = bulletSound;

        //반복 재생할건지. 반복 재생할 거면 true 한번만 재생할 거면 false
        source.loop = true;


        //3D 사운드, pan level key값 1로
        //1에 가까워질수록 3D 사운드에 가까워짐
        AnimationCurve ac = source.GetCustomCurve(AudioSourceCurveType.SpatialBlend);
        Keyframe[] keys = new Keyframe[1];

        for(int i = 0; i <keys.Length; i++)
        {
            keys[i].value = 1.0f;
        }
        ac.keys = keys;

        source.SetCustomCurve(AudioSourceCurveType.SpatialBlend, ac);
        //==============================================//

        //클립 재생
        source.Play();
    }

    private void Playsound()
    {
       
    }
}

 

 

 

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

public class SoundObject : MonoBehaviour
{
    public enum SoundState
    {
        Init,
        Play,
        Pause,
        Stop
    }

    private AudioSource audioSource = null;

    private SoundManager parent = null;

    private float wasAudioVol = 0;

    private SoundState state = SoundState.Init;

    private void Awake()
    {
        this.audioSource = this.GetComponent<AudioSource>();
    }

    public void PlayAudio(SoundManager parent, AudioClip audioClip, float vol, bool isLoop)
    {
        if (audioClip == null)
        {
            Debug.LogError("존재하지 않는 클립 입니다");
            StopAudio();
            return;
        }

        this.audioSource.clip = audioClip;
        this.parent = parent;
        this.audioSource.volume = vol;
        this.state = SoundState.Play;

        if (isLoop)
        {
            this.audioSource.loop = true;
            this.audioSource.Play();
        }
        else
        {
            this.audioSource.loop = false;
            this.audioSource.Play();
        }
    }

    public void PlayAudioOneShot(SoundManager parent, AudioClip audioClip, float vol)
    {
        PlayAudio(parent, audioClip, vol, false);
    }

    public void PlayAudioLoop(SoundManager parent, AudioClip audioClip, float vol)
    {
        PlayAudio(parent, audioClip, vol, true);
    }

    public void PauseAudio()
    {
        this.audioSource.Pause();
        this.state = SoundState.Pause;
    }

    public void StopAudio()
    {
        this.audioSource.Stop();
        ClearAudio();
    }

    public void ClearAudio()
    {
        this.state = SoundState.Stop;
        this.audioSource.clip = null;
        this.gameObject.SetActive(false);
        this.parent.ReturnPool(this);
    }

    private void Update()
    {
        if (this.audioSource.time >= this.audioSource.clip.length)
            ClearAudio();
    }
}

 

반응형