【Unity】サウンド管理クラスを見直す
いつも使っているSoundManager、AudioVolumeに色々問題があったので、見直しました。
1.SoundManager
プロジェクトのどこからでもサウンドが鳴らせる汎用SoundManagerです。以下の特徴があります。
(1)特徴
SEとボイスの再生を分けている。
SEとボイスを配列の中からランダム再生する変数。
BGMの一時停止と停止を分けている。
決定音とキャンセル音はSoundManager側に設定できる。
(2)使い方
プロジェクト内のどこからでも、SoundManager.i.をつけることで実行できます。音源は呼び出す側のオブジェクトに付けます。
[Header("SEまたはボイス")] public AudioClip playSe;
SoundManager.i.PlayVoice(playSe);
ただし、決定音とキャンセル音は何回も使用されるため、SoundManager側に付けます。
SoundManager.i.PlayClickSe();//決定音を再生
SoundManager.i.PlayCancelSe();//キャンセル音を再生
BGMの一時停止はポーズ時に、BGMに合わせたステージ構成をしている場合等に使用します。
SoundManager.i.PauseBgm();
SEやボイスのランダム再生はキャラゲー等で使用することが多いと思います。
[Header("ダメージ時ボイス")] public AudioClip [] DamageVoices;
SoundManager.i.RandomVoice(DamageVoices);
「ゆっくりまりちゃのだいっぼうけんっ」で多用しました。初期の作品なので全然機能もなくて遊びづらいんですが、ダウンロード数は多いんですよね…。いつかリメイクはしたいと思ってますが…。
(3)コード
using UnityEngine;
using UnityEngine.Audio;
public class SoundManager : MonoBehaviour {
[SerializeField] AudioSource bgmAudioSource;
[SerializeField] AudioSource seAudioSource;
[SerializeField] AudioSource voiceAudioSource;
[Header("決定音")] [SerializeField] AudioClip clickSe;
[Header("キャンセル音")] [SerializeField] AudioClip cancelSe;
public static SoundManager i;
void Awake() {
CheckInstance();
}
void CheckInstance() {
if (i == null) {
i = this;
DontDestroyOnLoad(gameObject);//シーン遷移しても破棄されない
} else {
Destroy(gameObject);
}
}
/// <summary>
/// BGMを再生
/// </summary>
/// <param name="clip"></param>
public void PlayBgm(AudioClip clip) {
if (clip){
bgmAudioSource.clip = clip;
bgmAudioSource.Play();
}
}
/// <summary>
/// BGMを再生(引数がない場合)
/// </summary>
public void PlayBgm() {
bgmAudioSource.Play();
}
/// <summary>
/// 引数のAudioClip(BGM)の中からランダムに再生
/// </summary>
/// <param name="clips"></param>
public void RandomBgm(params AudioClip[] clips) {
var randomIndex = UnityEngine.Random.Range(0, clips.Length);
bgmAudioSource.clip = (clips[randomIndex]);
bgmAudioSource.Play();
}
/// <summary>
/// BGMを一時停止
/// </summary>
public void PauseBgm() {
bgmAudioSource.Pause();
}
/// <summary>
/// BGMを停止
/// </summary>
public void StopBgm() {
bgmAudioSource.Stop();
}
/// <summary>
/// 効果音を再生
/// </summary>
/// <param name="clip"></param>
public void PlaySe(AudioClip clip) {
seAudioSource.PlayOneShot(clip);
}
/// <summary>
/// 引数のAudioClip(SE)の中からランダムに再生
/// </summary>
/// <param name="clips"></param>
public void RandomSe(params AudioClip[] clips) {
var randomIndex = UnityEngine.Random.Range(0, clips.Length);
seAudioSource.PlayOneShot(clips[randomIndex]);
}
/// <summary>
/// SEを停止
/// </summary>
public void StopSe() {
seAudioSource.Stop();
}
//決定音を再生
public void PlayClickSe() {
seAudioSource.PlayOneShot(clickSe);
}
//キャンセル音を再生
public void PlayCancelSe() {
seAudioSource.PlayOneShot(cancelSe);
}
/// <summary>
/// ボイスを再生
/// </summary>
/// <param name="clip"></param>
public void PlayVoice(AudioClip clip) {
voiceAudioSource.PlayOneShot(clip);
}
/// <summary>
/// 引数のAudioClip(Voice)の中からランダムに再生
/// </summary>
/// <param name="clips"></param>
public void RandomVoice(params AudioClip[] clips) {
var randomIndex = UnityEngine.Random.Range(0, clips.Length);
voiceAudioSource.PlayOneShot(clips[randomIndex]);
}
/// <summary>
/// Voiceを停止
/// </summary>
public void StopVoice() {
voiceAudioSource.Stop();
}
}
2.AudioVolume
オーディオボリュームを記録するクラスです。
以下の記事を参考にAudio MixerとSliderを作成します。
EasySaveを使用しているので、EasySaveがない人はPlayerPrefsに置き換えることで使用可能です。
3のSliderInitializerと組み合わせることで、Sliderがシーン開始時に非アクティブの状態でも問題なく作動します。
Sliderがシーンになくても問題ありません。
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;
public class AudioVolume : MonoBehaviour {
public AudioMixer audioMixer;//オーディオミキサーを登録
public Slider bGMSlider;//BGMのスライダーを登録
public Slider sESlider;//SEのスライダーを登録
public Slider voiceSlider;//ボイスのスライダーを登録
public Slider masterSlider;//マスターのスライダーを登録
public static AudioVolume i;//AudioVolumeクラスのインスタンスを作成
void Awake() {
CheckInstance();
}
void CheckInstance() {
if (i == null) {
i = this;
DontDestroyOnLoad(gameObject); //シーン遷移しても破棄されない
}
else {
Destroy(gameObject);
}
}
private void Start() {
//BGMとSEのスライダーの位置をロード。データがなければ最大値を入れる。
float bgmSliderPosition = ES3.Load<float>("BGM_SLIDER", 5.0f);
float seSliderPosition = ES3.Load<float>("SE_SLIDER", 5.0f);
float voiceSliderPosition = ES3.Load<float>("VOICE_SLIDER", 5.0f);
float masterSliderPosition = ES3.Load<float>("MASTER_SLIDER", 5.0f);
//BGMとSEのセットメソッドを呼び出す
SetBGM(bgmSliderPosition);
SetSE(seSliderPosition);
SetMaster(masterSliderPosition);
SetVoice(voiceSliderPosition);
//イベントリスナーを追加
AddListener();
}
public void AddListener() {
// イベントリスナーの追加
if(bGMSlider != null)
bGMSlider.onValueChanged.AddListener((value) => {
SetBGM(value);
ES3.Save<float>("BGM_SLIDER", value);
});
if(sESlider != null)
sESlider.onValueChanged.AddListener((value) => {
SetSE(value);
ES3.Save<float>("SE_SLIDER", value);
});
if(voiceSlider != null)
voiceSlider.onValueChanged.AddListener((value) => {
SetVoice(value);
ES3.Save<float>("VOICE_SLIDER", value);
});
if(masterSlider != null)
masterSlider.onValueChanged.AddListener((value) => {
SetMaster(value);
ES3.Save<float>("MASTER_SLIDER", value);
});
}
//オーディオミキサーの値を取得
public float GetMixerVolume(string parameterName) {
float value;
//オーディオミキサーから値を取得できた場合
if (audioMixer.GetFloat(parameterName, out value)) {
return Mathf.Pow(10, value / 20) * 5; // dBからスライダーの範囲に変換
}
return 0f; // デフォルト値
}
public void SetBGM(float bgmSliderPosition) {
//スライダーの位置から相対量をdBに変換してvolumeに入れる
var volume = Mathf.Clamp(Mathf.Log10(bgmSliderPosition / 5) * 20f, -80f, 0f);
//スライダーの位置のデータとビジュアルを合わせる
audioMixer.SetFloat("BGM", volume);
//bGMSliderがnullでない場合
if (bGMSlider != null) {
//オーディオミキサーにvolumeの値をセットする。
bGMSlider.value = bgmSliderPosition;
//スライダーの位置をセーブする。
ES3.Save<float>("BGM_SLIDER", bGMSlider.value);
}
}
public void SetSE(float seSliderPosition) {
var volume = Mathf.Clamp(Mathf.Log10(seSliderPosition/ 5) * 20f, -80f, 0f);
audioMixer.SetFloat("SE", volume);
if (sESlider != null) {
sESlider.value = seSliderPosition;
ES3.Save<float>("SE_SLIDER", sESlider.value);
}
}
public void SetVoice(float voiceSliderPosition) {
var volume = Mathf.Clamp(Mathf.Log10(voiceSliderPosition / 5) * 20f, -80f, 0f);
audioMixer.SetFloat("Voice", volume);
if(voiceSlider != null) {
voiceSlider.value = voiceSliderPosition;
ES3.Save<float>("VOICE_SLIDER", voiceSlider.value);
}
}
public void SetMaster(float masterSliderPosition) {
var volume = Mathf.Clamp(Mathf.Log10(masterSliderPosition / 5) * 20f, -80f, 0f);
audioMixer.SetFloat("Master", volume);
if (masterSlider != null) {
masterSlider.value = masterSliderPosition;
ES3.Save<float>("MASTER_SLIDER", masterSlider.value);
}
}
}
3.SliderInitializer
音量を調節するSliderにアタッチして使います。
シーン遷移時にSliderが非アクティブな場合、アクティブになったときにAudioVolumeから音量のデータを読み込んで、音量3なら3の位置にSliderが移動します。
using UnityEngine;
using UnityEngine.UI;
//ボリュームスライダーにアタッチして使用
//AudioVolumeクラスのスライダーを更新する
public class SliderInitializer : MonoBehaviour {
public enum SliderType { BGM, SE, Voice, Master }
public SliderType type; // インスペクタから設定するスライダーのタイプ
private Slider slider; // このコンポーネントがアタッチされているスライダー
void Awake() {
slider = GetComponent<Slider>();
}
void OnEnable() {
// スライダーが有効になるたびに、AudioVolumeのインスタンスと同期させる
if (AudioVolume.i != null) {
switch (type) {
case SliderType.BGM:
AudioVolume.i.bGMSlider = slider;
slider.value = AudioVolume.i.GetMixerVolume("BGM");
break;
case SliderType.SE:
AudioVolume.i.sESlider = slider;
slider.value = AudioVolume.i.GetMixerVolume("SE");
break;
case SliderType.Voice:
AudioVolume.i.voiceSlider = slider;
slider.value = AudioVolume.i.GetMixerVolume("Voice");
break;
case SliderType.Master:
AudioVolume.i.masterSlider = slider;
slider.value = AudioVolume.i.GetMixerVolume("Master");
break;
}
AudioVolume.i.AddListener();
}
}
}
2.注意事項
Sliderの「値の変更時(Single)」を以下の画像を参考に変更します。AudioVolume.SetBGMあるいはAudioVolume.SetSEが正しい。AudioVolume.SetBGM(float)あるいはAudioVolume.SetSE(float)は間違いなので注意!
3.参考記事
この記事が気に入ったらサポートをしてみませんか?