Unityで効果音を付けたい。しかし、効果音を鳴らすコードを書くのはは面倒だ。そうだ一括管理しようそうしよう。
※ この記事は
ぼくがかんがえたさいきょうのAudioManager【Unity】
ぼくがかんがえたさいきょうのAudioManager2【Unity】
をちょっとだけわかりやすく書いた記事です。
この記事でできること
- 効果音/BGMをScriptから鳴らすことができる
- 効果音/BGMを1つのScriptから複数鳴らすことができる
- AudioManagerをつくることができる
AudioManagerとは読んで字の如く、BGMやSEなどのオーディオファイルの再生や停止を管理するクラスです。
「音が鳴る物にAudioSouce付けて、全シーン毎にAudioListenerを用意して、オーディオファイルを追加する度にAudioClip付けて」ってのがめんどくさかったので、全シーン、どのスクリプトからもBGMとSEを操作出来るようにしたかったため作りました。(引用 ぼくがかんがえたさいきょうのAudioManager【Unity】)
用意するもの
- AudioManager.cs (新しく作る)
- Resourcesフォルダ
- 音源
AudioManager.csを書く
C#スクリプトを新規作成し、下のように書く
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// BGMとSEの管理をするマネージャ。シングルトン。
/// </summary>
public class AudioManager : AudioManager
{
//ボリューム保存用のkeyとデフォルト値
private const string BGM_VOLUME_KEY = "BGM_VOLUME_KEY";
private const string SE_VOLUME_KEY = "SE_VOLUME_KEY";
private const float BGM_VOLUME_DEFULT = 1.0f;
private const float SE_VOLUME_DEFULT = 1.0f;
//オーディオファイルのパス
private const string BGM_PATH = "Audio/BGM";
private const string SE_PATH = "Audio/SE";
//BGMがフェードするのにかかる時間
public const float BGM_FADE_SPEED_RATE_HIGH = 0.9f;
public const float BGM_FADE_SPEED_RATE_LOW = 0.3f;
private float _bgmFadeSpeedRate = BGM_FADE_SPEED_RATE_HIGH;
//次流すBGM名、SE名
private string _nextBGMName;
private string _nextSEName;
//BGMをフェードアウト中か
private bool _isFadeOut = false;
//BGM用、SE用に分けてオーディオソースを持つ
private AudioSource _bgmSource;
private List<AudioSource> _seSourceList;
private const int SE_SOURCE_NUM = 10;
//全AudioClipを保持
private Dictionary<string, AudioClip> _bgmDic, _seDic;
public static AudioManager Instance = null;
//=================================================================================
//初期化
//=================================================================================
private void Awake ()
{
if (this != Instance) {
Destroy (this);
return;
}
DontDestroyOnLoad (this.gameObject);
//オーディオリスナーおよびオーディオソースをSE+1(BGMの分)作成
gameObject.AddComponent<AudioListener>();
for(int i = 0; i < SE_SOURCE_NUM + 1; i++){
gameObject.AddComponent<AudioSource>();
}
//作成したオーディオソースを取得して各変数に設定、ボリュームも設定
AudioSource[] audioSourceArray = GetComponents<AudioSource> ();
_seSourceList = new List<AudioSource> ();
for(int i = 0; i < audioSourceArray.Length; i++){
audioSourceArray [i].playOnAwake = false;
if(i == 0){
audioSourceArray [i].loop = true;
_bgmSource = audioSourceArray [i];
_bgmSource.volume = PlayerPrefs.GetFloat (BGM_VOLUME_KEY, BGM_VOLUME_DEFULT);
}
else{
_seSourceList.Add (audioSourceArray [i]);
audioSourceArray [i].volume = PlayerPrefs.GetFloat (SE_VOLUME_KEY, SE_VOLUME_DEFULT);
}
}
//リソースフォルダから全SE&BGMのファイルを読み込みセット
_bgmDic = new Dictionary<string, AudioClip> ();
_seDic = new Dictionary<string, AudioClip> ();
object[] bgmList = Resources.LoadAll (BGM_PATH);
object[] seList = Resources.LoadAll (SE_PATH);
foreach (AudioClip bgm in bgmList) {
_bgmDic [bgm.name] = bgm;
}
foreach (AudioClip se in seList) {
_seDic [se.name] = se;
}
}
//=================================================================================
//SE
//=================================================================================
/// <summary>
/// 指定したファイル名のSEを流す。第二引数のdelayに指定した時間だけ再生までの間隔を空ける
/// </summary>
public void PlaySE (string seName, float delay = 0.0f)
{
if (!_seDic.ContainsKey (seName)) {
Debug.Log (seName + "という名前のSEがありません");
return;
}
_nextSEName = seName;
Invoke ("DelayPlaySE", delay);
}
private void DelayPlaySE ()
{
foreach(AudioSource seSource in _seSourceList){
if(!seSource.isPlaying){
seSource.PlayOneShot (_seDic [_nextSEName] as AudioClip);
return;
}
}
}
//=================================================================================
//BGM
//=================================================================================
/// <summary>
/// 指定したファイル名のBGMを流す。ただし既に流れている場合は前の曲をフェードアウトさせてから。
/// 第二引数のfadeSpeedRateに指定した割合でフェードアウトするスピードが変わる
/// </summary>
public void PlayBGM (string bgmName, float fadeSpeedRate = BGM_FADE_SPEED_RATE_HIGH)
{
if (!_bgmDic.ContainsKey (bgmName)) {
Debug.Log (bgmName + "という名前のBGMがありません");
return;
}
//現在BGMが流れていない時はそのまま流す
if (!_bgmSource.isPlaying) {
_nextBGMName = "";
_bgmSource.clip = _bgmDic [bgmName] as AudioClip;
_bgmSource.Play ();
}
//違うBGMが流れている時は、流れているBGMをフェードアウトさせてから次を流す。同じBGMが流れている時はスルー
else if (_bgmSource.clip.name != bgmName) {
_nextBGMName = bgmName;
FadeOutBGM (fadeSpeedRate);
}
}
/// <summary>
/// BGMをすぐに止める
/// </summary>
public void StopBGM ()
{
_bgmSource.Stop ();
}
/// <summary>
/// 現在流れている曲をフェードアウトさせる
/// fadeSpeedRateに指定した割合でフェードアウトするスピードが変わる
/// </summary>
public void FadeOutBGM (float fadeSpeedRate = BGM_FADE_SPEED_RATE_LOW)
{
_bgmFadeSpeedRate = fadeSpeedRate;
_isFadeOut = true;
}
private void Update ()
{
if (!_isFadeOut) {
return;
}
//徐々にボリュームを下げていき、ボリュームが0になったらボリュームを戻し次の曲を流す
_bgmSource.volume -= Time.deltaTime * _bgmFadeSpeedRate;
if (_bgmSource.volume <= 0) {
_bgmSource.Stop ();
_bgmSource.volume = PlayerPrefs.GetFloat (BGM_VOLUME_KEY, BGM_VOLUME_DEFULT);
_isFadeOut = false;
if (!string.IsNullOrEmpty (_nextBGMName)) {
PlayBGM (_nextBGMName);
}
}
}
//=================================================================================
//音量変更
//=================================================================================
/// <summary>
/// BGMとSEのボリュームを別々に変更&保存
/// </summary>
public void ChangeVolume (float BGMVolume, float SEVolume)
{
_bgmSource.volume = BGMVolume;
foreach(AudioSource seSource in _seSourceList){
seSource.volume = SEVolume;
}
PlayerPrefs.SetFloat (BGM_VOLUME_KEY, BGMVolume);
PlayerPrefs.SetFloat (SE_VOLUME_KEY, SEVolume);
}
}
空のオブジェクトにアタッチする。
重要
基本的には、ゲームの最初のシーンに置く。
AudioManagerオブジェクトはシングルトン化しており、シーンが変わっても破壊されないようになっている。
Resourcesフォルダを作る
名前を大文字小文字まで正確に書こう。
音源をフォルダに入れる
このようになる。
ここまでくればあとは使うのみ!
使い方
好きなScriptで
AudioManager.Instance.PlaySE("SE名");
AudioManager.Instance.PlayBGM("BGN名");
と書く。
引数に書いた名前の音源をResourcesフォルダから読み込み再生するのだ。例えば
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour {
// Use this for initialization
void Start () {
AudioManager.Instance.PlaySE("swish1");
}
// Update is called once per frame
void Update ()
{
if (Input.GetMouseButtonDown (0)) {
AudioManager.Instance.PlaySE("pickup01");
}
}
}
このように書く。
おまけ
音源について
基本mp3形式なら大丈夫。
他にも.aif,.wav,.ogg .xm,.mod,.it,.s3m 形式をサポートしている。
iPhoneの録音機能の場合はm4a形式となるので、変換が必要である。
私はだいたいフリー音源サイトで探している。
http://taira-komori.jpn.org/game01.html
サイト名の表記が必要となる音源サイトが多いので、公開する場合は注意すること。