【Unity】SoundManagerクラスを作ってみた。

#初めに
このクラスは自分なりに欲しい機能を追加しただけなので足りないと感じた方はここからさらに拡張してみてください。

#使用されているメソッド拡張&Managerクラス
* [SKLibrary](https://qiita.com/tilyakuda/items/f43bdd605682a181d6d8)
* [SaveLoadManager](https://qiita.com/tilyakuda/items/54df886eb390b7e7ac9f)
<br>これらは私が過去投稿したものを使用しております。これらのクラスを導入しないと動かないので導入してください。

#[ダウンロード先](https://github.com/Soumakakami/SoundManager)

#コード

```C#
using System.Collections.Generic;
using UnityEngine;
using SKLibrary;
using SKLibrary.SaveAndLoad;
using System;
using System.Collections;

public class SoundManager : SingletonMonoBehaviour<SoundManager>
{
	const string SAVE_FILE_NAME = "SoundInformation";		//セーブデータのファイル名
	const float BGM_FADE_TIME = 5f;							//フェードにかかる秒数

	[Serializable]
	public class SoundInfo
	{
		public float MainVolume;
		public float BackMusicVolume;
		public float SfxVolume;
	}
	[SerializeField]
	SoundInfo soundInfo;

	[SerializeField, Header("BGM")]
	AudioClip backMusic;
	public float MainVolume;
	public float BackMusicVolume;
	public float SfxVolume;
	public List<AudioSource> sfxList = new List<AudioSource>();

	GameObject backMusicObject;

	//クラス
	SaveLoadManager saveLoadManager;

	private void Start()
	{
		Initialize();
	}


	/// <summary>
	/// 初期化
	/// </summary>
	private void Initialize()
	{
		if (saveLoadManager==null)
		{
			saveLoadManager = FindObjectOfType<SaveLoadManager>();
		}

		soundInfo = (SoundInfo)saveLoadManager.Load(SAVE_FILE_NAME,SaveLoadManager.SaveFolder.Audio);



		//サウンドの設定データがなければ作成
		if (soundInfo==null)
		{
			soundInfo = new SoundInfo();
			Debug.Log("音声セーブデータを作成");
			soundInfo.BackMusicVolume = BackMusicVolume;
			soundInfo.MainVolume = MainVolume;
			soundInfo.SfxVolume = SfxVolume;
			SoundVolumeApplication();
			return;
		}
		VolumeAttach();
		//BGMが最初からアタッチしてあればそちらを流す
		if (backMusic != null)
		{
			RequestBackMusic(backMusic);
		}
	}


	/// <summary>
	/// バックミュージックをリクエストする
	/// </summary>
	/// <param name="_backMusic">流したいBGM</param>
	/// <param name="_overwrite">今流れているBGMを上書きするかどうか</param>
	/// <returns>バックミュージックを流しているAudioSource</returns>
	public AudioSource RequestBackMusic(AudioClip _backMusic, bool _overwrite = false, float _pitch = 1f)
	{
		
		AudioSource audioSource = null;
		//何も流れていなければ再生
		if (backMusicObject == null)
		{
			backMusicObject = new GameObject("BackMusicObject");
			audioSource = backMusicObject.AddComponent<AudioSource>();
			audioSource.loop = true;
			audioSource.pitch = Mathf.Clamp(_pitch, -3, 3);
			StartCoroutine(BackGroundMusicFade(_backMusic, audioSource, FadeMode.FadeIn));
		}

		//バックミュージックを上書き
		else if (backMusicObject != null && _overwrite == true)
		{
			audioSource = backMusicObject.GetComponent<AudioSource>();
			StartCoroutine(BackGroundMusicFade(_backMusic, audioSource, FadeMode.FadeOut));
		}

		return audioSource;
	}

	/// <summary>
	/// バックミュージックを止める
	/// </summary>
	/// <returns>バックミュージックを止められたかの結果 true or false</returns>
	public bool StopBackMusic()
	{
		bool result = false;
		if (backMusicObject != null)
		{
			backMusicObject.GetComponent<AudioSource>().Stop();
			result = true;
		}
		return result;
	}

	/// <summary>
	/// サウンドをリクエスとする
	/// </summary>
	/// <param name="_sound">流したいサウンド</param>
	/// <param name="_localPos">再生させたい位置</param>
	/// <param name="_loop">ループ</param>
	/// <param name="_pitch">ピッチ(-3～3)</param>
	/// <param name="_spatial">立体音響(0～1)</param>
	/// <returns>再生させているサウンドのAudioSource</returns>
	public AudioSource RequestSound(AudioClip _sound, Vector3 _localPos = default, bool _loop = false, float _pitch = 1f, float _spatial = 0f)
	{

		//Soundを鳴らす用のオブジェクトを生成
		GameObject tempAudio = new GameObject("TempAudio");
		//鳴らす位置を決める
		tempAudio.transform.position = _localPos;
		//AudioSourceをAddする
		AudioSource audioSource = tempAudio.AddComponent<AudioSource>() as AudioSource;
		//リストに格納
		sfxList.Allocation(audioSource, true);

		//ループさせるかどうか
		audioSource.loop = _loop;
		//音声を追加
		audioSource.clip = _sound;
		//音声を再生
		audioSource.Play();
		//ピッチ調整
		audioSource.pitch = Mathf.Clamp(_pitch, -3, 3);
		//立体音響
		audioSource.spatialBlend = Mathf.Clamp(_spatial, 0, 1);

		//ループでなければ
		if (_loop == false)
		{
			//音声が再生され終えたら削除
			Destroy(tempAudio, _sound.length);
		}

		//AudioSourceを返す
		return audioSource;
	}

	/// <summary>
	/// 現在なっている音に変更後の音量を適用させる
	/// </summary>
	public void SoundVolumeApplication()
	{
		soundInfo.MainVolume = MainVolume;
		soundInfo.BackMusicVolume = BackMusicVolume;
		soundInfo.SfxVolume = SfxVolume;

		saveLoadManager.Save(soundInfo, SAVE_FILE_NAME,SaveLoadManager.SaveFolder.Audio);

		//バックミュージックがなければ処理しない
		if (backMusicObject != null)
		{
			//音量再適用
			backMusicObject.GetComponent<AudioSource>().volume = MainVolume * BackMusicVolume;
		}

		//音量再適用
		for (int i = 0; i < sfxList.Count; i++)
		{
			if (sfxList[i] == null)
			{
				continue;
			}
			else
			{
				sfxList[i].volume = MainVolume * SfxVolume;
			}
		}
	}

	/// <summary>
	/// セーブしてあった値を読み込む
	/// </summary>
	public void VolumeAttach()
	{
		MainVolume = soundInfo.MainVolume;
		BackMusicVolume = soundInfo.BackMusicVolume;
		SfxVolume = soundInfo.SfxVolume;
		SoundVolumeApplication();
	}

	public enum FadeMode
	{
		FadeIn,
		FadeOut
	}
	/// <summary>
	/// BGMをフェードさせる
	/// </summary>
	/// <param name="_clip">再生させる曲</param>
	/// <param name="_audioSource">BGMのAudioSource</param>
	/// <param name="_fadeMode">フェードモード</param>
	/// <returns></returns>
	IEnumerator BackGroundMusicFade(AudioClip _clip,AudioSource _audioSource,FadeMode _fadeMode)
	{
		float volume;
		switch (_fadeMode)
		{
			case FadeMode.FadeIn:
				//最大値を決定
				volume = MainVolume*BackMusicVolume;
				//現在の音量を0に
				_audioSource.volume = 0;
				//音声割り当て
				_audioSource.clip = _clip;
				//再生
				_audioSource.Play();

				//少しづつ音量を増やす
				while (_audioSource.volume < volume)
				{
					_audioSource.volume += Time.deltaTime/BGM_FADE_TIME;
					yield return null;
				}
				_audioSource.volume = volume;
				break;

			case FadeMode.FadeOut:

				Debug.Log("フェードアウト開始");
				//音量を保存
				volume = _audioSource.volume;

				//少しずつ減らす
				while (_audioSource.volume > 0)
				{
					_audioSource.volume -= Time.deltaTime / BGM_FADE_TIME;
					yield return null;
				}
				Debug.Log("フェードアウト終了");
				break;
		}
		yield break;
	}
}

```
#まとめ
まだデバックが完全にすんではいませんし、機能の追加もまだしたいですがとりあえずできているとこまで載せます。
不具合などありましたらご連絡ください。