LoginSignup
2
3

More than 1 year has passed since last update.

Unityで簡単なSoundManager

Posted at

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

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

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;
    }
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3