はじめに
設定画面など、スライダーやチェックボックス(Toggle)を扱うことがあります。多分ソースコードはこんな感じになっています。
using UnityEngine;
using UnityEngine.UI;
namespace hoge
{
public class ConfigController : MonoBehaviour
{
[SerializeField] Toggle BGMToggle, SEToggle, VoiceToggle;
[SerializeField] Slider BGMSlider, SESlider, VoiceSlder;
[SerializeField] InputField MemoInputField;
[SerializeField] AudioSource BGMSource, SESource, VoiceSource;
void Update()
{
// AudioSourceのミュート状態を制御
BGMSource.mute = BGMToggle.isOn;
SESource.mute = SEToggle.isOn;
VoiceSource.mute = VoiceToggle.isOn;
// AudioSourceの音量を制御
BGMSource.volume = BGMSlider.value;
SESource.volume = SESlider.value;
VoiceSource.volume = VoiceSlder.value;
}
}
}
これらは多くの場合、アプリが終了しても保持しておく必要があると思うので、今回は拡張メソッドを使って実現してみました。
使い方
まずSaveStateExtensions.csをDLし、プロジェクト内にインポートします。
次に保存したいコンポーネントに対して、Start()
内などで以下の様に呼び出してあげるだけです。
void Start()
{
// Toggleの場合
BGMToggle.SaveState("BGMToggle");
SEToggle.SaveState("SEToggle");
VoiceToggle.SaveState("VoiceToggle");
// Sliderの場合
BGMSlider.SaveState("BGMSlider");
SESlider.SaveState("SESlider");
VoiceSlder.SaveState("VoiceSlder");
// InputFieldの場合
MemoInputField.SaveState("MemoInputField");
}
引数のkey
だけは重複しないように気を付けて下さい。(nameof(BGMToggle)
を渡してもいいかも)
アプローチ
ソースコード全文はこのようになっています。
Gits: SaveStateExtensions.cs
using UnityEngine;
using UnityEngine.UI;
public static class SaveStateExtensions
{
public static void SaveState(this Toggle toggle, string key)
{
key = $"{new System.Diagnostics.StackFrame(1).GetMethod().ReflectedType}+{key}";
Debug.Log(key);
toggle.isOn = PlayerPrefs.GetInt(key, 0) == 1;
toggle.onValueChanged.AddListener(isOn => PlayerPrefs.SetInt(key, isOn ? 1 : 0));
}
public static void SaveState(this Slider slider, string key)
{
key = $"{new System.Diagnostics.StackFrame(1).GetMethod().Name}+{key}";
slider.value = PlayerPrefs.GetFloat(key, 0f);
slider.onValueChanged.AddListener(value => PlayerPrefs.SetFloat(key, value));
}
public static void SaveState(this InputField inputField, string key)
{
key = $"{new System.Diagnostics.StackFrame(1).GetMethod().Name}+{key}";
inputField.text = PlayerPrefs.GetString(key, string.Empty);
inputField.onValueChanged.AddListener(value => PlayerPrefs.SetString(key, value));
}
public static void SaveState(this Dropdown dropdown, string key)
{
key = $"{new System.Diagnostics.StackFrame(1).GetMethod().Name}+{key}";
dropdown.value = PlayerPrefs.GetInt(key, 0);
dropdown.onValueChanged.AddListener(value => PlayerPrefs.SetInt(key, value));
}
}
SaveStateToggle
を例に見てみると、やっていることは①PlayerPrefs.GetInt()
で取得した値をToggle
の初期値として代入し、②Toggle
の変更が合った場合のイベント(toggle.onValueChanged
)内でPlayerPrefs.SetInt()
を呼んでいます。
public static void SaveStateToggle(this Toggle toggle, string key)
{
key = $"{new System.Diagnostics.StackFrame(1).GetMethod().ReflectedType}+{key}";
toggle.isOn = PlayerPrefs.GetInt(key, 0) == 1;
toggle.onValueChanged.AddListener(isOn => PlayerPrefs.SetInt(key, isOn ? 1 : 0));
}
少し工夫しているのかkey
の生成で、System.Diagnostics.StackFrame(1).GetMethod().ReflectedType
を使って呼び出し元のクラス名を先頭に追加しています。先の例では"hoge.ConfigController+BGMToggle"
がkey
になる形です。こうすることによって、このメソッドを多くの場所で利用してもkey
の衝突が起きにくくしています。
最後に
今回は保存にPlayerPrefs
を使っていますが、異常終了時には正しく保存されない場合があります。(PlayerPrefs.Save();
で明示的に保存することもできます)
あくまで簡易的なものですので、その点に気をつけてぜひご活用ください。