Skip to content

Instantly share code, notes, and snippets.

@Islington036
Last active June 8, 2022 08:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Islington036/c0e25f522e8eb41954438992e15fb71d to your computer and use it in GitHub Desktop.
Save Islington036/c0e25f522e8eb41954438992e15fb71d to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
[System.Serializable]
public class AudioData
{
// 名前(インスペクターからの登録)
public string name = "";
// AudioClip
public AudioClip Clip = null;
// Audioの音量設定用変数
public float SoundVolume = 1;
}
public class SoundManager : SingletonMonoBehaviour<SoundManager>
{
//=============================================================================
// 変数
//=============================================================================
// ボリューム関連
[SerializeField, Range(0, 1), Tooltip("マスタ音量")]
private float volume = 1;
[SerializeField, Range(0, 1), Tooltip("BGMの音量")]
private float BGM_Total_Volume = 0.1f;
[SerializeField, Range(0, 1), Tooltip("SEの音量")]
private float SE_Total_Volume = 0.2f;
[SerializeField, Tooltip("BGMの同時再生可能数")]
private int BGM_PlaybackNum = 5;
[SerializeField, Tooltip("SEの同時再生可能数")]
private int SE_PlaybackNum = 5;
// ミュート中
[SerializeField]
private bool Mute = false;
// AudioSource
private AudioSource[] BGM_Sources;
private AudioSource[] SE_Sources;
// オーディオ情報
[SerializeField]
List<AudioData> BGMData;
[SerializeField]
List<AudioData> SEData;
//=============================================================================
// 起動時
//=============================================================================
protected override void Awake()
{
// 継承元を呼び出し
base.Awake();
// 同時再生可能数を元にAudioSourceを初期化
BGM_Sources = new AudioSource[BGM_PlaybackNum];
SE_Sources = new AudioSource[SE_PlaybackNum];
// BGM用にAudioSourceコンポーネントを取得
for (int i = 0; i < BGM_Sources.Length; i++)
{
// AudioSourceを追加
BGM_Sources[i] = gameObject.AddComponent<AudioSource>();
// 初期ボリュームをセット
BGM_Sources[i].volume = BGM_Total_Volume * volume;
}
// SE用にAudioSourceコンポーネントを取得
for (int i = 0; i < SE_Sources.Length; i++)
{
// AudioSourceを追加
SE_Sources[i] = gameObject.AddComponent<AudioSource>();
// 初期ボリュームをセット
SE_Sources[i].volume = SE_Total_Volume * volume;
}
// 呼び出し用変数に名前を入力
if (BGMData == null || SEData == null)
{
Debug.LogError(BGMData + "か" + SEData + " が空です");
}
}
//=============================================================================
// 音量変更系統
//=============================================================================
/// <summary>
/// BGMボリューム変更
/// </summary>
public float BGM_TotalVolume
{
set
{
BGM_Total_Volume = Mathf.Clamp01(value);
// 全てのBGMのAudioSourceに設定
for (int i = 0; i < BGM_Sources.Length; i++)
{
BGM_Sources[i].volume = BGM_Total_Volume * volume;
}
}
get{ return BGM_Total_Volume; }
}
/// <summary>
/// SEボリューム変更
/// </summary>
public float SE_TotalVolume
{
set
{
SE_Total_Volume = Mathf.Clamp01(value);
// 全てのSEのAudioSourceに設定
for (int i = 0; i < SE_Sources.Length; i++)
{
SE_Sources[i].volume = SE_Total_Volume * volume;
}
}
get{ return SE_Total_Volume; }
}
/// <summary>
/// ミュート選択
/// </summary>
public bool IsMute
{
set
{
Mute = value;
if(value)
{
StopBGMAll();
StopSEAll();
}
}
get { return Mute; }
}
//=============================================================================
// 名前の一致を検索
//=============================================================================
/// <summary> 曲名もしくはファイル名と一致するか判定</summary>
/// <param name="Data"> オーディオデータ </param>
/// <param name="name"> 判定する名前 </param>
/// <returns> 曲名もしくはタイトル名と一致したらtrueを返す </returns>
private bool FindTitleMatch(AudioData Data, string name)
{
if(Data.name.Equals(name) || Data.Clip.name.Equals(name)) { return true; }
return false;
}
//=============================================================================
// ファイル名もしくは名前からAudioClipを検索
//=============================================================================
/// <summary> ファイル名もしくは名前からAudioClipを検索 </summary>
/// <param name="Data"> オーディオデータ配列 </param>
/// <param name="name"> 判定する名前 </param>
/// <returns> 見つからなかった場合はnullを返す </returns>
private AudioClip FindAudioClip(AudioData[] Data, string name)
{
foreach(AudioData Audio in Data)
{
if(FindTitleMatch(Audio, name)){ return Audio.Clip; }
}
return null;
}
//=============================================================================
// タイトルから配列の番号を検索
//=============================================================================
/// <summary>
/// 曲の名前から配列の格納番号を検索
/// </summary>
/// <param name="name">曲の名前</param>
/// <param name="isBGM">BGMかSEかの指定</param>
private int GetIndex(string name, bool isBGM)
{
if (isBGM)
{
for (int i = 0; i < BGMData.Count; i++)
{
if (FindTitleMatch(BGMData[i], name))
{
return i;
}
}
}
else
{
for (int i = 0; i < SEData.Count; i++)
{
if (FindTitleMatch(SEData[i], name))
{
return i;
}
}
}
Debug.LogError("指定された名前のファイルは登録されていません");
return -1;
}
//=============================================================================
// 再生中ではない空いているAudioSourceを検索
//=============================================================================
/// <summary> 空いているAudioSourceを検索 </summary>
/// <param name="Source"> 検索するAudioSource配列 </param>
/// <returns> 再生可能な番号を返す </returns>
private int PlayingNumberSearch(AudioSource[] Source)
{
// 再生するBGM_Sourcesの番号
int AudioSourceIndex = -1;
// 再生終了しているAudioSourceを見つける
for (int i = 0; i < Source.Length; i++)
{
// 再生していないAudioSourceを検索
if (Source[i].time == 0.0f && !Source[i].isPlaying)
{
// 再生するAudioSourceを空にする
Source[i].clip = null;
// 再生する番号を決定
AudioSourceIndex = i;
}
}
// 空いている番号が見つからなかった場合
if (AudioSourceIndex == -1)
{
// 先頭のBGM_Sourcesを更新
AudioSourceIndex = 0;
}
// 再生可能な番号を返す
return AudioSourceIndex;
}
//=============================================================================
// 音量をセット
//=============================================================================
/// <summary> BGMの音量をセット </summary>
/// <param name="name"> ファイル名 </param>
/// <param name="SoundVolume"> 設定する音量 </param>
/// <returns> 設定が反映されたらtrue </returns>
public bool BGM_SoundVolumeSet(string name, float SoundVolume)
{
for (int i = 0; i < BGMData.Count; i++)
{
if(FindTitleMatch(BGMData[i], name))
{
BGMData[i].SoundVolume = SoundVolume;
return true;
}
}
return false;
}
/// <summary> SEの音量をセット </summary>
/// <param name="name"> ファイル名 </param>
/// <param name="SoundVolume"> 設定する音量 </param>
/// <returns> 設定が反映されたらtrue </returns>
public bool SE_SoundVolumeSet(string name, float SoundVolume)
{
for (int i = 0; i < SEData.Count; i++)
{
if (FindTitleMatch(SEData[i], name))
{
SEData[i].SoundVolume = SoundVolume;
return true;
}
}
return false;
}
//=============================================================================
// 名前から再生中のAudioSourceを検索を検索
//=============================================================================
/// <summary> 名前から再生中のAudioSourceを検索を検索 </summary>
/// <param name="Source"> 検索するAudioSource配列 </param>
/// <param name="name"> 曲名 </param>
/// <returns> 曲が再生されている場合は番号、されていない場合は-1を返す </returns>
private int AudioSourceNameToNumber(AudioData[] Data, AudioSource[] Source, string name)
{
// AudioSourceを検索
for (int i = 0; i < Source.Length; i++)
{
// nullの場合は以下の処理を行わない
if(Source[i].clip == null) { continue; }
// オーディオデータを検索
foreach (AudioData Audio in Data)
{
// ファイル名もしくは名前から一致するAudioClipを検索
if(FindTitleMatch(Audio, name))
{
// 曲名と一致するものが合った場合
if (Source[i].clip.name.Equals(Audio.Clip.name))
{
// 格納されている配列の番号を返す
return i;
}
}
}
}
// 見つからなかった場合は-1を返す
return -1;
}
//=============================================================================
// BGM系統
//=============================================================================
/// <summary>
/// BGM再生
/// </summary>
/// <param name="bgmType">BGMのタイトル</param>
/// <param name="loop">ループの有無</param>
/// <param name="PlayVolume">再生時のボリューム</param>
public void PlayBGM(string bgmType, bool loop, float PlayVolume = -1)
{
// ミュートでは無い場合
if (!IsMute)
{
// タイトルからインデックスに変換
int index = GetIndex(bgmType, true);
// BGMの指定にエラーが起こった場合は終了
if (index < 0 || BGMData.Count <= index)
{
return;
}
// 再生するBGM_Sourcesの番号
int AudioSourceIndex = PlayingNumberSearch(BGM_Sources);
// 音量を設定する場合
if (PlayVolume != -1)
{
BGM_SoundVolumeSet(bgmType, PlayVolume);
}
// BGM再生開始
BGM_Sources[AudioSourceIndex].clip = BGMData[index].Clip;
BGM_Sources[AudioSourceIndex].loop = loop;
BGM_Sources[AudioSourceIndex].volume = BGM_TotalVolume * volume * BGMData[index].SoundVolume;
BGM_Sources[AudioSourceIndex].Play();
}
}
/// <summary>
/// BGM再生(オーディオソース指定)
/// </summary>
/// <param name="bgmType"> BGMのタイトル </param>
/// <param name="Source"> オーディオソース </param>
/// <param name="loop"> ループの有無 </param>
/// <param name="PlayVolume"> 再生時のボリューム </param>
public void PlayBGM(string bgmType, ref AudioSource Source, bool loop, float PlayVolume = -1)
{
// ミュートでは無い場合
if (!IsMute)
{
// タイトルからインデックスに変換
int index = GetIndex(bgmType, true);
// BGMの指定にエラーが起こった場合は終了
if (index < 0 || BGMData.Count <= index)
{
return;
}
// 音量を設定する場合
if (PlayVolume != -1)
{
BGM_SoundVolumeSet(bgmType, PlayVolume);
}
// BGM再生開始
Source.clip = BGMData[index].Clip;
Source.loop = loop;
Source.volume = BGM_TotalVolume * volume * BGMData[index].SoundVolume;
Source.Play();
}
}
/// <summary>
/// BGM再生(配列のインデックス直接指定)
/// インデックスの確認処理を省いたため、処理は軽くなりました
/// </summary>
/// <param name="bgmType">BGMのインデックス</param>
/// <param name="loop">ループの有無</param>
public void PlayBGM(int index, bool loop)
{
// 再生するBGM_Sourcesの番号
int AudioSourceIndex = PlayingNumberSearch(BGM_Sources);
if (!IsMute)
{
// BGM再生開始
BGM_Sources[AudioSourceIndex].clip = BGMData[index].Clip;
BGM_Sources[AudioSourceIndex].loop = loop;
BGM_Sources[AudioSourceIndex].volume = BGM_TotalVolume * volume * BGMData[index].SoundVolume;
BGM_Sources[AudioSourceIndex].Play();
}
}
/// <summary>
/// BGM完全停止
/// </summary>
public void StopBGM(string name)
{
// 名前から再生停止するBGMを検索する
int index = AudioSourceNameToNumber(BGMData.ToArray(), BGM_Sources, name);
// BGMが見つかった場合
if (index != -1)
{
BGM_Sources[index].Stop();
BGM_Sources[index].clip = null;
}
}
/// <summary>
/// 全てのBGMを完全停止
/// </summary>
public void StopBGMAll()
{
// BGMを検索
for (int i = 0; i < BGM_Sources.Length; i++)
{
// nullの場合は以下の処理を行わない
if (BGM_Sources[i].clip == null) { continue; }
// 全てのBGMを停止
BGM_Sources[i].Stop();
BGM_Sources[i].clip = null;
}
}
/// <summary>
/// BGM一時停止
/// </summary>
public void MuteBGM(string name)
{
// 名前から再生停止するBGMを検索する
int index = AudioSourceNameToNumber(BGMData.ToArray(), BGM_Sources, name);
// BGMが見つかった場合
if (index != -1)
{
BGM_Sources[index].Stop();
}
}
/// <summary>
/// 一時停止した同じBGMを再生(再開)
/// </summary>
public void ResumeBGM(string name)
{
// 名前から再生停止するBGMを検索する
int index = AudioSourceNameToNumber(BGMData.ToArray(), BGM_Sources, name);
// BGMが見つかった場合
if (index != -1)
{
BGM_Sources[index].Play();
}
}
//=============================================================================
// SE系統
//=============================================================================
/// <summary>
/// SE再生
/// </summary>
/// <param name="seType"> 曲名 </param>
/// <param name="loop"> ループの有無 </param>
/// <param name="PlayVolume"> 再生時のボリューム </param>
/// <param name="Singleton"> 同じ曲は再生しない </param>
public void PlaySE(string seType, bool loop = false, float PlayVolume = -1, bool Singleton = false)
{
// ミュートでは無い場合
if (!IsMute)
{
// タイトルからインデックスに変換
int index = GetIndex(seType, false);
// SEの指定にエラーが起こった場合は終了
if (index < 0 || SEData.Count <= index)
{
return;
}
// 単体設定の場合はAudioSourceを検索して、同じ名前があったら再生しない
if (Singleton)
{
foreach (var SE in SE_Sources)
{
// 存在しない場合は以下の処理を行わない
if (SE.clip == null) { continue; }
// AudioSourceから検索
if (SE.clip.name.Equals(SEData[index].Clip.name) &&
SE.time != 0.0f &&
SE.isPlaying)
{
// 同じ名前が見つかった場合は終了
return;
}
}
}
// 音量を設定する場合
if (PlayVolume != -1)
{
SE_SoundVolumeSet(seType, PlayVolume);
}
// 再生するBGM_Sourcesの番号
int AudioSourceIndex = PlayingNumberSearch(SE_Sources);
// SE再生開始
SE_Sources[AudioSourceIndex].clip = SEData[index].Clip;
SE_Sources[AudioSourceIndex].volume = SE_TotalVolume * volume * SEData[index].SoundVolume;
SE_Sources[AudioSourceIndex].loop = loop;
SE_Sources[AudioSourceIndex].Play();
}
}
/// <summary>
/// SE再生(オーディオソース指定)
/// </summary>
/// <param name="seType"> 曲名 </param>
/// <param name="Source"> オーディオソース(参照) </param>
/// <param name="loop"> ループの有無 </param>
/// <param name="PlayVolume"> 再生時のボリューム </param>
public void PlaySE(string seType, ref AudioSource Source, bool loop = false, float PlayVolume = -1)
{
// ミュートでは無い場合
if (!IsMute)
{
// タイトルからインデックスに変換
int index = GetIndex(seType, false);
// SEの指定にエラーが起こった場合は終了
if (index < 0 || SEData.Count <= index)
{
return;
}
// 音量を設定する場合
if (PlayVolume != -1)
{
SE_SoundVolumeSet(seType, PlayVolume);
}
// SE再生開始
Source.clip = SEData[index].Clip;
Source.volume = SE_TotalVolume * volume * SEData[index].SoundVolume;
Source.loop = loop;
Source.Play();
}
}
/// <summary>
/// SE再生(配列のインデックス直接指定)
/// インデックスの確認処理を省いたため、処理は軽くなりました
/// </summary>
/// <param name="bgmType">SEのインデックス</param>
public void PlaySE(int index)
{
// 再生するBGM_Sourcesの番号
int AudioSourceIndex = PlayingNumberSearch(SE_Sources);
if (!IsMute)
{
// SE再生開始
SE_Sources[AudioSourceIndex].clip = SEData[index].Clip;
SE_Sources[AudioSourceIndex].volume = SE_TotalVolume * volume * SEData[index].SoundVolume;
SE_Sources[AudioSourceIndex].Play();
}
}
/// <summary>
/// SE停止
/// </summary>
public void StopSE(string name)
{
// 名前から再生停止するSEを検索する
int index = AudioSourceNameToNumber(SEData.ToArray(), SE_Sources, name);
// SEが見つかった場合
if (index != -1)
{
SE_Sources[index].Stop();
SE_Sources[index].clip = null;
}
}
/// <summary>
/// 全てのSEを完全停止
/// </summary>
public void StopSEAll()
{
// SEを検索
for (int i = 0; i < SE_Sources.Length; i++)
{
// nullの場合は以下の処理を行わない
if (SE_Sources[i].clip == null) { continue; }
// 全てのBGMを停止
SE_Sources[i].Stop();
SE_Sources[i].clip = null;
}
}
public string GetSourceName(string name)
{
foreach (AudioData Audio in SEData)
{
if (FindTitleMatch(Audio, name)) { return Audio.name; }
}
return "";
}
public void PauseSEAll()
{
foreach (var SE in SE_Sources)
{
SE.Pause();
}
}
public void PauseReleaseSEAll()
{
foreach (var SE in SE_Sources)
{
if (SE.time != 0.0f && !SE.isPlaying)
{
SE.Play();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment