AudioManagerを仕上げてみました。
【前の記事】シングルトンの実装についてはこちら
→【Unity】なんちゃらManagerクラスを作ろう(シングルトン)
イメージ
自分がAudioManagerを作ろうって思った時点で思い描いた仕様はこんな感じ。- デザイナ上でBGMやSEを好きなだけセットできる。
- 好きな場所からいつでも再生、停止できる。
- 再生する音源は音声ファイル名で指定する。
- BGMは1つだけ再生。
- SEは指定した数まで同時再生可能。
実装
できました。ソースは長いので一番下に載せときました。
使い方
AudioManagerの配置
・空のGameObjectを作成・名前をAudioManagerとかにしとく
・AddComponentでAudioManagerを追加
![]() |
| 追加直後の状態 |
AudioClipをセット
・mp3ファイルとかをHierarchyビューにドロップ(これでAudioClipができる)
・AudioClipの名前は分かりやすい名前にしておく
(呼び出すときに使うため)
・BGMListにAudioClipを好きなだけ追加
・SEListにAudioClipを好きなだけ追加
・MaxSEはSEの最大同時再生数です。好きな値で。
![]() |
| BGM2つ、SE3つセットしてみた所 |
テスト用スクリプト書いてみる
・MainCameraのAudioListenerを削除(or 無効化)・空のGameObjectにこんな感じのコンポーネントを付ける
using UnityEngine;
public class script : MonoBehaviour {
void OnGUI()
{
if(GUI.Button(new Rect(10,100,100,50),"BGM1"))
{
AudioManager.Instance.PlayBGM("bgm1");
}
if(GUI.Button(new Rect(110,100,100,50),"BGM2"))
{
AudioManager.Instance.PlayBGM("bgm2");
}
if(GUI.Button(new Rect(210,100,100,50),"BGMSTOP"))
{
AudioManager.Instance.StopBGM();
}
if(GUI.Button(new Rect(10,200,100,50),"SE1"))
{
AudioManager.Instance.PlaySE("se1");
}
if(GUI.Button(new Rect(110,200,100,50),"SE2"))
{
AudioManager.Instance.PlaySE("se2");
}
if(GUI.Button(new Rect(210,200,100,50),"SE3"))
{
AudioManager.Instance.PlaySE("se3");
}
if(GUI.Button(new Rect(310,200,100,50),"SESTOP"))
{
AudioManager.Instance.StopSE();
}
}
}
実行!BGMが鳴る!切り替えられる!停止できる!
SEが鳴る!いっぱい鳴る!
完璧っす。
ソース
AudioManager.cs
using UnityEngine;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public class AudioManager : SingletonMonoBehaviour<AudioManager> {
public List<AudioClip> BGMList;
public List<AudioClip> SEList;
public int MaxSE = 10;
private AudioSource bgmSource = null;
private List<AudioSource> seSources = null;
private Dictionary<string,AudioClip> bgmDict = null;
private Dictionary<string,AudioClip> seDict = null;
public void Awake()
{
if(this != Instance)
{
Destroy(this);
return;
}
DontDestroyOnLoad(this.gameObject);
//create listener
if(FindObjectsOfType(typeof(AudioListener)).All(o => !((AudioListener)o).enabled))
{
this.gameObject.AddComponent<AudioListener>();
}
//create audio sources
this.bgmSource = this.gameObject.AddComponent<AudioSource>();
this.seSources = new List<AudioSource>();
//create clip dictionaries
this.bgmDict = new Dictionary<string, AudioClip>();
this.seDict = new Dictionary<string, AudioClip>();
Action<Dictionary<string,AudioClip>,AudioClip> addClipDict = (dict, c) => {
if(!dict.ContainsKey(c.name))
{
dict.Add(c.name,c);
}
};
this.BGMList.ForEach(bgm => addClipDict(this.bgmDict,bgm));
this.SEList.ForEach(se => addClipDict(this.seDict,se));
}
public void PlaySE(string seName)
{
if(!this.seDict.ContainsKey(seName)) throw new ArgumentException(seName + " not found","seName");
AudioSource source = this.seSources.FirstOrDefault(s => !s.isPlaying);
if(source == null)
{
if(this.seSources.Count >= this.MaxSE)
{
Debug.Log("SE AudioSource is full");
return;
}
source = this.gameObject.AddComponent<AudioSource>();
this.seSources.Add(source);
}
source.clip = this.seDict[seName];
source.Play();
}
public void StopSE()
{
this.seSources.ForEach(s => s.Stop());
}
public void PlayBGM(string bgmName)
{
if(!this.bgmDict.ContainsKey(bgmName)) throw new ArgumentException(bgmName + " not found","bgmName");
if(this.bgmSource.clip == this.bgmDict[bgmName]) return;
this.bgmSource.Stop();
this.bgmSource.clip = this.bgmDict[bgmName];
this.bgmSource.Play();
}
public void StopBGM()
{
this.bgmSource.Stop();
this.bgmSource.clip = null;
}
}
ポイント
・実行にはSingletonMonoBehaviourクラスが必要です。→こちら・複数Scene跨いでも使えます。
・Scene内にAudioListenerが無い場合は生成します。
・AudioSourceを動的に生成します。
まとめ
やりたいと思ったことは実現できました。でもListとかDictionaryとかLinqをガンガン使ってるので
ゲーム開発って視点で見ると無駄の多いソースなのかも。
アプリ開発始めたころは省メモリ意識してたんだけど
結構動いてくれるから気にしないで書いちゃうのよね。
ソース載っけてみたので
”もっとこうした方がいいよ。" とか "自分はこんな風にしてるよ。”
っていうのがある方は是非おしえてください!
人のソース読みたい…。
それじゃまた!
→Unity系記事まとめ


