Unityやってるワン

Unityで勉強したことを備忘録として記事にしていきます

音声を管理・制御するクラスを作ってみた

Unityで勉強したことを備忘録として記事にしていきます
とか言いつつ、しばらくサボってしまいました…
これからは週1回くらいのペースで、Unityで勉強したことを記事にしていきたいです。


今回はUnityでの音声関連の制御について勉強して、スクリプトを作ったので記事にしてみました。まずは音声の再生や停止などを制御するSoundPlayer.csです。



SoundPlayer.cs

using System.Collections;
using UnityEngine;

[RequireComponent(typeof(AudioSource))]
public class SoundPlayer : MonoBehaviour
{
    /// <summary>サウンドID</summary>
    private int m_soundID = 0;

    /// <summary>オーディオソース</summary>
    private AudioSource m_source;

    /// <summary>再生時間</summary>
    private float m_playTime = 0.0f;

    /// <summary>一時停止フラグ</summary>
    private bool m_isPauseNow = false;



    /// <summary>
    /// オブジェクト生成時
    /// </summary>
    private void Awake ()
    {
        m_source  = gameObject.GetComponent<AudioSource>();
        m_soundID = SoundManager.Instance.AddPlayer(this);
    }

    /// <summary>
    /// オブジェクト破棄時
    /// </summary>
    private void OnDestroy ()
    {
        SoundManager.Instance.RemovePlayer(m_soundID);
    }

    /// <summary>
    /// 再生
    /// </summary>
    public void Play ()
    {
        if (m_source.clip != null)
        {
            if (m_isPauseNow)
            {
                m_source.time = m_playTime;
                m_source.UnPause();
            }
            else
            {
                m_source.Stop();
                m_source.Play();
            }
            m_isPauseNow = false;
        }
    }

    /// <summary>
    /// 停止
    /// </summary>
    public void Stop ()
    {
        if (!m_source.isPlaying)
        {
            m_source.Stop();
            m_isPauseNow = false;
        }
    }

    /// <summary>
    /// 一時停止
    /// </summary>
    public void Pause ()
    {
        m_source.Pause();
        m_playTime = m_source.time;
        m_isPauseNow = true;
    }

    /// <summary>
    /// 音量セット
    /// </summary>
    /// <param name="_volume">音量</param>
    public void SetVolume (float _volume)
    {
        m_source.volume = _volume;
    }

    /// <summary>
    /// 再生速度セット
    /// </summary>
    /// <param name="_pitch">再生速度</param>
    public void SetPitch (float _pitch)
    {
        m_source.pitch  = _pitch;
    }
}

作ったとはいうものの、ほとんどAudioSourceが再生、停止などをやってくれるので自力でやってる感はあまりないです…
AudioSourceの処理以外に、Awakeで実態生成時にSoundPlayerのIDを取得して、SoundPlayerが破棄された時にOnDestroyでIDも破棄するようにしています。
このIDは以下のSoundManager.csでSoundPlayerを管理する際に使用しています。
他にはRequireComponentで必ずAudioSourceがアタッチされるようにしています。



SoundManager.cs

using System.Collections.Generic;
using System.Collections;
using UnityEngine;

public class SoundManager : SingletonClass<SoundManager>
{
    /// <summary>サウンドリスト</summary>
    public Dictionary<int, SoundPlayer> m_soundList = new Dictionary<int, SoundPlayer>();



    /// <summary>
    /// 実体生成時
    /// </summary>
    private void Awake ()
    {
        DontDestroyOnLoad(this);
    }

    /// <summary>
    /// プレイヤー追加
    /// </summary>
    /// <param name="_soundPlayer">サウンドプレイヤー</param>
    /// <returns>未使用ID</returns>
    public int AddPlayer (SoundPlayer _soundPlayer)
    {
        //使用されていないIDをサーチ
        int id = 0;
        while (true)
        {
            if (!m_soundList.ContainsKey(id))
            {
                m_soundList.Add(id, _soundPlayer);
                return id;
            }
            id++;
        }
    }

    /// <summary>
    /// プレイヤー破棄
    /// </summary>
    /// <param name="_id">サウンドID</param>
    public void RemovePlayer (int _id)
    {
        if (m_soundList.ContainsKey(_id))
        {
            m_soundList.Remove(_id);
        }
    }

    /// <summary>
    /// リスト破棄
    /// </summary>
    public void Clear ()
    {
        m_soundList.Clear();
    }

    /// <summary>
    /// 再生
    /// </summary>
    public void Play ()
    {
        foreach (SoundPlayer soundPlayer in m_soundList.Values)
        {
            soundPlayer.Play();
        }
    }

    /// <summary>
    /// 停止
    /// </summary>
    public void Stop ()
    {
        foreach (SoundPlayer soundPlayer in m_soundList.Values)
        {
            soundPlayer.Stop();
        }
    }

    /// <summary>
    /// 一時停止
    /// </summary>
    public void Pause ()
    {
        foreach (SoundPlayer soundPlayer in m_soundList.Values)
        {
            soundPlayer.Pause();
        }
    }

    /// <summary>
    /// 音量設定
    /// </summary>
    /// <param name="_volume">音量</param>
    public void SetVolume (float _volume)
    {
        foreach (SoundPlayer soundPlayer in m_soundList.Values)
        {
            soundPlayer.SetVolume(_volume);
        }
    }
}

SoundManagerではシーン内のSoundPlayerを一括管理します。
以前、記事に書いたSingletonClassを継承しているため、シーンが切り替わっても破棄されずに残ります。シーンの切り替え時にフェードイン・フェードアウトで全サウンドの音量を徐々に変えたい場合やポーズ画面で全サウンドを一時停止させたい場合に、SoundManagerで制御ができます。


学生の頃、DirectXC言語でサウンドの制御関連の処理を作った時にかなり苦戦した記憶がありますが、Unityだとあっという間に作れました。ゲームエンジンの恩恵ですね..


次回は入力関連について勉強して記事にまとめてみたいと思います。