Unityで簡単なSoundManager

めちゃ久しぶりの投稿です。（最近私用で忙しい、、、）

今後まだ改良予定ですがUnityでSoundManagerを製作しました。
まだ簡単な実装なので今後は3D対応、フェードイン、アウトの対応をする予定です。

https://github.com/ryota0303F/UnitySoundManager

###SoundList.cs
アセットのセット用

```
namespace GameSound
{
    public class SoundList : MonoBehaviour
    {
        [SerializeField] AudioClip[] audioClipList;

        [SerializeField] string[] tagClipList;

        Dictionary<string, AudioClip> _audioClipList = null;


        void Start()
        {
            SetDictionary();
        }

        void SetDictionary()
        {
            _audioClipList = new Dictionary<string, AudioClip>();
            for (int i = 0; i < audioClipList.Length; i++)
            {
                if (tagClipList.Length <= i)
                    break;

                _audioClipList.Add(tagClipList[i], audioClipList[i]);
            }
        }

        public Dictionary<string, AudioClip> GetDictionary()
        {
            return _audioClipList;
        }

    }
}
```

###SoundManager.cs
```
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace GameSound
{
    //使用するサウンドの種類
    public enum UsingSoundTyp
    {
        None,
        SE,         //効果音
        BGM,        //BGM
        SE_3D,      //3D(今後実装予定)
    }

    //サウンドの再生方法
    public enum PlaySoundTyp
    {
        None,
        Single,     //一回再生する
        Loop,       //一定条件が来るまでループ
        LoopNum,    //指定回数ループ
    }

    /// <summary>
    /// サウンドの通知
    /// </summary>
    public class SoundInfo
    {
        public SoundInfo() { }

        //サウンドのタイプ
        public UsingSoundTyp m_usingSoundTyp;   //念のためつけてるけど現在の使用用途は謎

        //サウンドの再生方法
        public PlaySoundTyp m_playSoundTyp;

        //使用するサウンドの文字列
        public string m_usingSound;

        //使用するサウンドがLoopだった際に何回繰り返すか
        public int m_loopNum = -1;

        //サウンド終了時に呼ばれる関数の登録
        public Func<bool> m_endFunc;

        //サウンドを一時停止させるかの確認用関数の登録
        //trueでストップ
        public Func<bool> m_pauseFunc;

        //一時停止させたサウンドをPlayするかの確認用関数の登録
        //trueでPlay
        public Func<bool> m_unpauseFunc;

        //SoundPlayerを終了させる
        //trueで終了
        public Func<bool> m_stopFunc;
    }
    
    /// <summary>
    /// サウンドを再生するためのクラス
    /// </summary>
    public class SoundPlayer
    {
        public SoundPlayer(SoundInfo _soundInfo, AudioSource _audioSource, int _index)
        {
            m_soundInfo = _soundInfo;
            m_audioSource = _audioSource;
            m_index = _index;
            Inst();
        }

        //通知データ
        public SoundInfo m_soundInfo = null;

        //使用しているAudioSource
        public AudioSource m_audioSource = null;

        //使用中のindex
        public int m_index = -1;

        int m_loopCount;

        bool m_playFlg = true;

        /// <summary>
        /// 初期化
        /// </summary>
        void Inst()
        {
            m_loopCount = 0;
            m_playFlg = true;
            m_audioSource.PlayDelayed(0);
        }

        /// <summary>
        /// SoundPlayerの終了
        /// </summary>
        void ReleaseAudioSource()
        {
            if (m_soundInfo.m_endFunc != null) 
                m_soundInfo.m_endFunc();

            SoundManager.Instance.ReleaseAudioSource(m_index, this);
        }

        /// <summary>
        /// サウンド終了後の処理
        /// </summary>
        void SoundEnd()
        {
            switch(m_soundInfo.m_playSoundTyp)
            {
                case PlaySoundTyp.Single:       //1回のみ
                    ReleaseAudioSource();
                    break;
                case PlaySoundTyp.Loop:         //ループ
                    m_audioSource.PlayDelayed(0);
                    break;
                case PlaySoundTyp.LoopNum:      //指定回数ループ
                    m_loopCount++;
                    if (m_loopCount >= m_soundInfo.m_loopNum)
                    {
                        ReleaseAudioSource();
                    }
                    else
                    {
                        m_audioSource.PlayDelayed(0);
                    }
                    break;
                default:
                    ReleaseAudioSource();
                    break;
            }

        }

        /// <summary>
        /// 更新
        /// </summary>
        public void Update()
        {
            //一時停止
            if(m_soundInfo.m_pauseFunc != null&& m_playFlg)
            {
                if(m_soundInfo.m_pauseFunc())
                {
                    m_audioSource.Pause();
                    m_playFlg = false;
                }
            }

            //再開
            if (m_soundInfo.m_unpauseFunc != null && !m_playFlg)
            {
                if (m_soundInfo.m_unpauseFunc())
                {
                    m_audioSource.UnPause();
                    m_playFlg = true;
                }
            }

            //SoundPlayerの終了
            if (m_soundInfo.m_stopFunc != null)
            {
                if (m_soundInfo.m_stopFunc())
                {
                    m_audioSource.Stop();
                    m_playFlg = false;
                    ReleaseAudioSource();
                }
            }

            //サウンド終了時
            if (!m_audioSource.isPlaying && m_playFlg)
            {
                SoundEnd();
            }
        }


    }

    public class SoundManager : Singleton<SoundManager>
    {
        [Header("SoundManagerは常にHierarchy下になるようにする")]

        [SerializeField] SoundList _soundList = null;

        //オブジェクトプール
        [SerializeField] AudioSource[] _audioSourceList = null;
        List<bool> _audioSourceListFlg = null;

        //サウンドリスト
        Dictionary<string, AudioClip> _audioClipList = null;

        //通知リスト
        public List<SoundInfo> _soundInfosList { get; private set; } = null;

        //再生しているサウンドのリスト
        public List<SoundPlayer> _soundPlayerList { get; private set; } = null;

        //SoundPlayerリストの解放予定のリスト
        List<SoundPlayer> _releasesoundPlayerList = null;

        void Start()
        {
            Inst();
        }
        
        void Update()
        {
            InfoListCheck();
            SoundUpdate();
        }

        /// <summary>
        /// 初期化
        /// </summary>
        public void Inst()
        {
            //AudioClipDictionaryの取得
            _soundInfosList = new List<SoundInfo>();
            if (_soundList != null)
            {
                _audioClipList = _soundList.GetDictionary();
            }
            else
            {
                Debug.LogError("Could not get 'SoundList'");
                return;
            }

            //AudioSourceListの準備
            if (_audioSourceList != null)
            {
                _audioSourceListFlg = new List<bool>();
                for (int i = 0; i < _audioSourceList.Length; i++)
                {
                    _audioSourceListFlg.Add(false);
                }
            }
            else
            {
                Debug.LogError("There is no 'AudioSourceList'");
                return;
            }

            if(_soundPlayerList == null)
                _soundPlayerList = new List<SoundPlayer>();

            if (_releasesoundPlayerList == null) 
                _releasesoundPlayerList = new List<SoundPlayer>();

        }

        /// <summary>
        /// 通知チェック
        /// </summary>
        void InfoListCheck()
        {
            if (_soundInfosList.Count <= 0)
                return;

            foreach(var info in _soundInfosList)
            {
                if(!_audioSourceListFlg.Contains(false))
                {
                    Debug.LogError("No 'AudioSource' available");
                    continue;
                }

                if (!_audioClipList.ContainsKey(info.m_usingSound))
                {
                    Debug.LogError($"No '{info.m_usingSound}' AudioClip");
                    continue;
                }

                AudioClip audioClip = _audioClipList[info.m_usingSound];

                int index = 0;
                for (int i = 0; i < _audioSourceListFlg.Count; i++)
                {
                    if (!_audioSourceListFlg[i])
                    {
                        index = i;
                        _audioSourceListFlg[i] = true;
                        break;
                    }
                }

                _audioSourceList[index].clip = audioClip;

                SoundPlayer soundPlayer = new SoundPlayer(info, _audioSourceList[index], index);
                _soundPlayerList.Add(soundPlayer);
            }
            _soundInfosList.Clear();
        }

        /// <summary>
        /// 通知を取得
        /// </summary>
        /// <param name="_soundInfo"></param>
        public void SetInfo(SoundInfo _soundInfo)
        {
            _soundInfosList.Add(_soundInfo);
        }

        /// <summary>
        /// 使用中のAudioSourceの解放
        /// </summary>
        /// <param name="_index"></param>
        public void ReleaseAudioSource(int _index, SoundPlayer _soundPlayer)
        {
            _audioSourceList[_index].clip = null;
            _audioSourceListFlg[_index] = false;

            _releasesoundPlayerList.Add(_soundPlayer);
        }

        /// <summary>
        /// 解放予定リストの確認
        /// </summary>
        void ReleaseCheck()
        {
            //解放予定があれば解放
            if (_releasesoundPlayerList.Count > 0)
            {
                foreach (var _soundPlayer in _releasesoundPlayerList)
                {
                    _soundPlayerList.Remove(_soundPlayer);
                }
                _releasesoundPlayerList.Clear();
            }
        }

        /// <summary>
        /// サウンドの更新
        /// </summary>
        void SoundUpdate()
        {
            if (_soundPlayerList == null)
                return;

            foreach(var _soundPlayer in _soundPlayerList)
            {
                _soundPlayer.Update();
            }
            ReleaseCheck();
        }


    }
}
```



###使用例

```
 void Update()
    {
        if(Input.GetKeyDown(KeyCode.P))
        {
            SoundInfo soundInfo = new SoundInfo()
            {
                m_usingSoundTyp = UsingSoundTyp.SE,
                m_playSoundTyp = PlaySoundTyp.LoopNum,
                m_loopNum = 3,
                m_usingSound="SE",
                m_endFunc = TestEnd,
            };
            SoundManager.Instance.SetInfo(soundInfo);
        }
        if (Input.GetKeyDown(KeyCode.O))
        {
            SoundInfo soundInfo = new SoundInfo()
            {
                m_usingSoundTyp = UsingSoundTyp.BGM,
                m_playSoundTyp = PlaySoundTyp.Single,
                m_usingSound = "BGM",
                m_endFunc = TestEnd,
            };
            SoundManager.Instance.SetInfo(soundInfo);
        }
        if(Input.GetKeyDown(KeyCode.J))
        {
            SoundInfo soundInfo = new SoundInfo()
            {
                m_usingSoundTyp = UsingSoundTyp.BGM,
                m_playSoundTyp = PlaySoundTyp.Loop,
                m_usingSound = "BGM",
                m_endFunc = TestEnd,
                m_pauseFunc = Pause,
                m_unpauseFunc = UnPause,
                m_stopFunc = Stop,
            };
            SoundManager.Instance.SetInfo(soundInfo);
        }

    }

    bool TestEnd()
    {
        Debug.Log("End");

        return true;
    }

    bool Pause()
    {
        if (Input.GetKeyDown(KeyCode.I))
        {
            return true;
        }
        return false;
    }

    bool UnPause()
    {
        if (Input.GetKeyDown(KeyCode.U))
        {
            return true;
        }
        return false;
    }

    bool Stop()
    {
        if (Input.GetKeyDown(KeyCode.Y))
        {
            return true;
        }
        return false;
    }
```