追記 2020/03/16
githubにて公開しました。
https://github.com/wakepon/SoundManager
追記 2016/08/17
すいません。この記事の後に改良版を作りました↓↓↓
http://waken.hatenablog.com/entry/2016/08/17/090031
自作ゲーム用に簡単なSoundManagerを作りました。
以下を参考にさせていただきました。
Unityでの音(サウンド)管理(SoundManager Ver.β)
一番のポイントは、Resources/Audio/BGMに置いたものとResources/Audio/SEに置いたものが自動で登録されて名前引きで呼び出せるようになっていること。
その他のポイントは以下
- 一応名前引きが遅かった時のためにインデックス指定でも呼べる
- 速度調査は未検証...
- 同じSEは1Frameに1個しか鳴らないようになっている。
- Singletonである
- SEのチャンネル数は16まで。16チャンネル中、空いているところを探して発音
- 参考元は、BGM、SEに加えてVoiceというのもあったが、自分はVoiceを扱うことがあまりないので特別分けていない。
[System.Serializable]
public class SoundVolume{
public float bgm = 1.0f;
public float se = 1.0f;
public bool mute = false;
public void Reset(){
bgm = 1.0f;
se = 1.0f;
mute = false;
}
}
public class SoundManager : SingletonMonoBehaviour< SoundManager > {
public SoundVolume volume = new SoundVolume();
private AudioClip[] seClips;
private AudioClip[] bgmClips;
private Dictionary<string,int> seIndexes = new Dictionary<string,int>();
private Dictionary<string,int> bgmIndexes = new Dictionary<string,int>();
const int cNumChannel = 16;
private AudioSource bgmSource;
private AudioSource[] seSources = new AudioSource[cNumChannel];
Queue<int> seRequestQueue = new Queue< int >();
//------------------------------------------------------------------------------
void Awake () {
if( this != Instance )
{
Destroy(this);
return;
}
bgmSource = gameObject.AddComponent<AudioSource>();
bgmSource.loop = true;
for(int i = 0 ; i < seSources.Length ; i++ ){
seSources[i] = gameObject.AddComponent<AudioSource>();
}
seClips = Resources.LoadAll<AudioClip>("Audio/SE");
bgmClips = Resources.LoadAll<AudioClip>("Audio/BGM");
for( int i = 0; i < seClips.Length; ++i )
{
seIndexes[seClips[i].name] = i;
}
for( int i = 0; i < bgmClips.Length; ++i )
{
bgmIndexes[bgmClips[i].name] = i;
}
/* Debug.Log("se ========================"); */
/* foreach(var ac in seClips ) { Debug.Log( ac.name ); } */
/* Debug.Log("bgm ========================"); */
/* foreach(var ac in bgmClips ) { Debug.Log( ac.name ); } */
}
//------------------------------------------------------------------------------
void Update()
{
bgmSource.mute = volume.mute;
foreach(var source in seSources ){
source.mute = volume.mute;
}
bgmSource.volume = volume.bgm;
foreach(var source in seSources ){
source.volume = volume.se;
}
int count = seRequestQueue.Count;
if( count != 0 )
{
int sound_index = seRequestQueue.Dequeue();
playSeImpl( sound_index );
}
}
//------------------------------------------------------------------------------
private void playSeImpl( int index )
{
if( 0 > index || seClips.Length <= index ){
return;
}
foreach(AudioSource source in seSources){
if( false == source.isPlaying ){
source.clip = seClips[index];
source.Play();
return;
}
}
}
//------------------------------------------------------------------------------
public int GetSeIndex( string name )
{
return seIndexes[name];
}
//------------------------------------------------------------------------------
public int GetBgmIndex( string name )
{
return bgmIndexes[name];
}
//------------------------------------------------------------------------------
public void PlayBgm( string name ){
int index = bgmIndexes[name];
PlayBgm( index );
}
//------------------------------------------------------------------------------
public void PlayBgm( int index ){
if( 0 > index || bgmClips.Length <= index ){
return;
}
if( bgmSource.clip == bgmClips[index] ){
return;
}
bgmSource.Stop();
bgmSource.clip = bgmClips[index];
bgmSource.Play();
}
//------------------------------------------------------------------------------
public void StopBgm(){
bgmSource.Stop();
bgmSource.clip = null;
}
//------------------------------------------------------------------------------
public void PlaySe( string name )
{
PlaySe( GetSeIndex( name ) );
}
//一旦queueに溜め込んで重複を回避しているので
//再生が1frame遅れる時がある
//------------------------------------------------------------------------------
public void PlaySe( int index )
{
if( !seRequestQueue.Contains( index ) )
{
seRequestQueue.Enqueue( index );
}
}
//------------------------------------------------------------------------------
public void StopSe(){
ClearAllSeRequest();
foreach(AudioSource source in seSources){
source.Stop();
source.clip = null;
}
}
//------------------------------------------------------------------------------
public void ClearAllSeRequest()
{
seRequestQueue.Clear();
}
}
SingletonMonoBehaviourをご存知でない方は、お手数ですがググってみてください。