LoginSignup
15
12

More than 5 years have passed since last update.

Unityのゲームに効果音をつけよう AudioManager

Last updated at Posted at 2017-12-24

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#スクリプトを新規作成し、下のように書く

AudioManager.cs
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);
    }

}

空のオブジェクトにアタッチする。

image.png

重要
基本的には、ゲームの最初のシーンに置く。
AudioManagerオブジェクトはシングルトン化しており、シーンが変わっても破壊されないようになっている。

Resourcesフォルダを作る

image.png

名前を大文字小文字まで正確に書こう。

音源をフォルダに入れる

効果音はSEフォルダ、BGMはBGMフォルダに入れよう。
image.png

このようになる。

image.png

ここまでくればあとは使うのみ!

使い方

好きな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

サイト名の表記が必要となる音源サイトが多いので、公開する場合は注意すること。

15
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
12