UnityでBGM・SEの音量設定を作る|SliderとPlayerPrefsで設定を保存

Unity

はじめに

Unityで制作しているクイズゲームに、オプション画面を追加しました。

今回実装したのは、

  • 設定画面の表示・非表示
  • SliderによるBGM音量変更
  • SliderによるSE音量変更
  • PlayerPrefsによる音量設定の保存
  • ゲームを再起動したときの音量設定の読み込み

です。

最初は、

bgmAudioSource.volume = volume;

で音量を変更できれば設定は終わりだと思っていました。

しかし、この方法ではUnityの再生を終了すると音量が元に戻ってしまいます。

そこで今回は、PlayerPrefs を使って設定を保存しました。

オプション画面を作る

まずタイトル画面に設定ボタンを配置しました。

Hierarchyは次のような構成です。

Canvas
├ GameStartButton
├ OptionButton
└ OptionPanel
├ SettingText
├ BGMText
├ BGMSlider
├ SEText
├ SESlider
└ CloseButton

OptionPanel はゲーム開始時には非表示にします。

void Start()
{
optionPanel.SetActive(false);
}

設定ボタンを押したときに表示します。

public void OnOptionButton()
{
optionPanel.SetActive(true);
}

Closeボタンでは再び非表示にします。

public void OnCloseButton()
{
optionPanel.SetActive(false);
}

これで、

設定ボタン
↓
OptionPanel表示
↓
Close
↓
OptionPanel非表示

という基本的な設定画面ができました。

SliderでBGM音量を変更する

AudioManagerではBGM用とSE用のAudioSourceを分けています。

[SerializeField] private AudioSource bgmAudioSource;
[SerializeField] private AudioSource seAudioSource;

BGM音量を変更する関数を作ります。

public void SetBGMVolume(float volume)
{
bgmAudioSource.volume = volume;
}

SliderのValueを 0~1 に設定しておけば、その値をそのままAudioSource.volumeに使用できます。

Slider = 0
↓
volume = 0
↓
無音

Slider = 0.5
↓
volume = 0.5

Slider = 1
↓
volume = 1

Sliderの On Value Changed にSetBGMVolume()を設定すると、Sliderを動かすたびに現在の値がvolumeに渡されます。

On Value Changedとは?

Sliderで音量を変更するときに使用したのが、Sliderコンポーネントにある On Value Changed です。

最初は「なぜSliderを動かすだけで SetBGMVolume() が呼ばれるのか」がよく分かっていませんでした。

On Value Changed は簡単にいうと、

SliderのValueが変更されたときに、登録した処理を実行するイベント。

Buttonの On Click と比較すると分かりやすいです。

Button
↓
On Click
↓
ボタンが押されたら処理を実行

Slider
↓
On Value Changed
↓
Sliderの値が変わったら処理を実行

Sliderの値をSetBGMVolume(関数)に渡す

AudioManagerには、BGM音量を変更するために次の関数を用意しました。

public void SetBGMVolume(float volume)
{
bgmAudioSource.volume = volume;
PlayerPrefs.SetFloat(“BGMVolume”, volume);
}

ここで重要なのが、float volume という引数です。

Sliderの On Value Changed から現在のValueを、この volume に渡すことができます。

例えばSliderを動かしてValueが 0.3 になった場合、

Slider
Value = 0.3
↓
On Value Changed
↓
SetBGMVolume(0.3)
↓
volume = 0.3

という流れになります。

そのため、

bgmAudioSource.volume = volume;

このとき実質、

bgmAudioSource.volume = 0.3f;

と同じことになります。

結果として、Sliderを動かした位置に合わせてBGM音量も変化します。

Dynamic floatを選択する

SliderのInspectorにある On Value Changed (Single) に SetBGMVolume() を登録するときは、Sliderの現在値を渡すために Dynamic float の方を選択します。

これによって、自分で 0.5 などの固定値を指定するのではなく、SliderのValueが自動的に引数へ渡されます。

「Sliderの値が変わったので、この値を使って登録した関数を実行してください」と橋渡ししているのが On Value Changed です。

SEも同じように変更する

SEも基本的な仕組みは同じです。

public void SetSEVolume(float volume)
{
seAudioSource.volume = volume;
}

BGMとSEでAudioSourceを分けているため、それぞれ別々に音量を調整できます。

問題:Unityを停止すると音量が元に戻る

ここまでで音量は変更できました。

しかし、Unityの再生を停止して再び実行すると、設定した音量が元に戻ってしまいました。

理由は、

bgmAudioSource.volume = volume;

が現在のAudioSourceの音量を変更しているだけだからです。

これは設定を保存しているわけではありません。

そこでPlayerPrefsを使用します。

PlayerPrefsでBGM音量を保存する

BGM音量変更時に、次の1行を追加します。

public void SetBGMVolume(float volume)
{
 bgmAudioSource.volume = volume;

 PlayerPrefs.SetFloat(“BGMVolume”, volume);
}

重要なのが、

PlayerPrefs.SetFloat(“BGMVolume”, volume);

これは、

"BGMVolume"という名前でvolumeの値を保存する

という意味です。

例えばSliderを0.3にした場合、

volume = 0.3
↓
// 現在のBGM音量を変更
bgmAudioSource.volume = 0.3
↓
// 0.3を保存
BGMVolume → 0.3

ここで、

bgmAudioSource.volume = volume;

と

PlayerPrefs.SetFloat(“BGMVolume”, volume);

は役割が違います。

前者は音量変更、後者は値の保存です。

保存したBGM音量を読み込む

保存しただけでは、AudioSourceには戻りません。

ゲーム開始時に保存した値を取得します。

float bgmVolume =
PlayerPrefs.GetFloat(“BGMVolume”, 1.0f);

bgmAudioSource.volume = bgmVolume;

GetFloat()は、

PlayerPrefs.GetFloat(“BGMVolume”, 1.0f);

と書いた場合、

"BGMVolume"という名前で保存されている値を取得する。
保存されていなければ1.0fを返す。

という意味です。

例えば前回、

BGMVolume → 0.3

と保存していれば、

PlayerPrefs.GetFloat(“BGMVolume”, 1.0f);

から返ってくるのは0.3です。

一方、初回起動でまだ何も保存されていなければ1.0が返ってきます。

SetFloatとGetFloatの違い

今回、一番混乱したのがここでした。

整理すると非常にシンプルです。

処理役割
AudioSource.volume現在の音量を変更
PlayerPrefs.SetFloat()数値を保存
PlayerPrefs.GetFloat()保存した数値を取得

例えば、

PlayerPrefs.SetFloat(“BGMVolume”, 0.3f);

で保存して、

float bgmVolume =
PlayerPrefs.GetFloat(“BGMVolume”, 1.0f);

で取り出します。

SE音量も保存する

SEについても同じです。

public void SetSEVolume(float volume)
{
seAudioSource.volume = volume;
PlayerPrefs.SetFloat(“SEVolume”, volume);
}

読み込みは、

float seVolume =PlayerPrefs.GetFloat(“SEVolume”, 1.0f);
seAudioSource.volume = seVolume;

"BGMVolume"と"SEVolume"という異なる名前を使うことで、それぞれ別の値として保存できます。

まとめ

今回の実装で特に重要だったのは、「音量を変更すること」と「音量を保存すること」は別の処理だという点です。

bgmAudioSource.volume = volume;

は現在の音量変更。

PlayerPrefs.SetFloat(“BGMVolume”, volume);

は保存。

PlayerPrefs.GetFloat(“BGMVolume”, 1.0f);

は保存した値の取得です。

この3つを分けて考えることで、PlayerPrefsの役割が理解しやすくなりました。

コメント