名前を入力する、音量をスライダーで調整する、フルスクリーンのチェックを切り替える、画質を選ぶ・・・プレイヤーが値を入力・選択するUIを、まとめてご紹介します。最後に、それらを組み合わせた設定画面を作ってみましょう!
この記事で学べること
- Input Field(文字の入力)の使い方
- Slider(スライダー)で値を調整する方法
- Toggle(チェックボックス)の使い方
- Dropdown(選択肢から選ぶ)の使い方
- 値が変わったときに処理を呼ぶ方法(onValueChanged)
- PlayerPrefsで設定を保存する方法
前提知識
この記事のスクリプトは、どれも先頭に次のusingが必要です(9-4で説明しました)。
using UnityEngine;
using UnityEngine.UI;
using TMPro;
Input Field(文字の入力)
Input Fieldを作る
- Canvasを右クリック>UI>Input Field – TextMeshPro
Input Fieldの設定
- Placeholder:何も入力していないときに薄く表示される文字(子のPlaceholderのText Inputで変更)
- Character Limit:入力できる最大の文字数(0は制限なし)
- Content Type:入力できる文字の種類(Standard:なんでも、Integer Number:整数だけ、Password:●で隠す など)
日本語を入力する場合は、Input Fieldの中のText(TMP)とPlaceholderのフォントを、9-3で作った日本語のフォントアセットにしておきましょう。
入力された文字を受け取る
「NameInput」という名前でスクリプトを作ります。
using UnityEngine;
using TMPro;
public class NameInput : MonoBehaviour
{
[SerializeField] private TMP_InputField nameInputField;
[SerializeField] private TMP_Text greetingText;
void Start()
{
// 入力が確定したとき(Enterを押す・欄の外をクリック)に呼ぶ
nameInputField.onEndEdit.AddListener(OnNameEntered);
}
void OnDestroy()
{
nameInputField.onEndEdit.RemoveListener(OnNameEntered);
}
private void OnNameEntered(string playerName)
{
if (playerName == "")
{
greetingText.text = "名前を入力してね";
return;
}
greetingText.text = "ようこそ、" + playerName + "さん!";
}
}
TMP_InputField型で、Input Fieldを参照しますinputField.textで、今入力されている文字を読めます- onEndEdit:入力が確定したときに呼ばれる。受け取ったメソッドには、入力された文字が渡されます
- 1文字打つたびに反応させたいときは、onValueChangedを使います
Slider(スライダー)
9-4ではHPバーとして使いましたが、プレイヤーが動かして値を決めるのにも使えます。
Sliderを作る
- Canvasを右クリック>UI>Slider
Sliderの設定
- Direction:どちら向きに増えるか(Left To Right など)
- Min Value / Max Value:値の範囲。音量なら0〜1
- Whole Numbers:チェックすると整数だけになる
音量を調整する
「VolumeSlider」という名前でスクリプトを作ります。
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class VolumeSlider : MonoBehaviour
{
[SerializeField] private Slider volumeSlider;
[SerializeField] private TMP_Text volumeText;
void Start()
{
volumeSlider.minValue = 0f;
volumeSlider.maxValue = 1f;
volumeSlider.value = AudioListener.volume;
volumeSlider.onValueChanged.AddListener(OnVolumeChanged);
OnVolumeChanged(volumeSlider.value);
}
void OnDestroy()
{
volumeSlider.onValueChanged.RemoveListener(OnVolumeChanged);
}
// スライダーが動くたびに呼ばれる(今の値が渡される)
private void OnVolumeChanged(float value)
{
AudioListener.volume = value; // ゲーム全体の音量(0〜1)
volumeText.text = "音量: " + Mathf.RoundToInt(value * 100) + "%";
}
}
- onValueChanged:値が変わるたびに呼ばれ、新しい値が渡されます
AudioListener.volumeは、ゲーム全体の音量です。BGMと効果音を別々に調整したい場合は、AudioMixerという仕組みを使います
Toggle(チェックボックス)
Toggleを作る
- Canvasを右クリック>UI>Toggle
- 子のLabelの文字を「フルスクリーン」などに変える(Labelは古いText(Legacy)の場合があるので、そのときはTextMeshProのテキストに作り直すか、9-3のフォントを設定します)
Toggleの設定
- Is On:チェックが入っているか(true / false)
- Group:同じToggle Groupに入れたToggleは、どれか1つしかOnにならない(ラジオボタンになる)
フルスクリーンを切り替える
「ScreenToggle」という名前でスクリプトを作ります。
using UnityEngine;
using UnityEngine.UI;
public class ScreenToggle : MonoBehaviour
{
[SerializeField] private Toggle fullscreenToggle;
void Start()
{
fullscreenToggle.isOn = Screen.fullScreen;
fullscreenToggle.onValueChanged.AddListener(OnFullscreenChanged);
}
void OnDestroy()
{
fullscreenToggle.onValueChanged.RemoveListener(OnFullscreenChanged);
}
private void OnFullscreenChanged(bool isOn)
{
Screen.fullScreen = isOn;
Debug.Log("フルスクリーン: " + isOn);
}
}
toggle.isOnで、今チェックが入っているかを読み書きできます- フルスクリーンの切り替えは、エディタの再生中には反映されません。ビルドしたゲーム(第10章)で確認できます
Dropdown(選択肢から選ぶ)
Dropdownを作る
- Canvasを右クリック>UI>Dropdown – TextMeshPro
Dropdownの設定
- Options:選択肢のリスト。Inspectorの「+」で追加できる
- Value:選ばれている選択肢の番号(0から始まる)
画質を選ぶ
選択肢はスクリプトから作ることもできます。プロジェクトに設定されている画質の一覧(Project Settings>Quality)を、そのまま選択肢にしてみましょう。「QualityDropdown」という名前でスクリプトを作ります。
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class QualityDropdown : MonoBehaviour
{
[SerializeField] private TMP_Dropdown qualityDropdown;
void Start()
{
// プロジェクトに設定されている画質の名前を、選択肢にする
qualityDropdown.ClearOptions();
qualityDropdown.AddOptions(new List<string>(QualitySettings.names));
// 今の画質を選んだ状態にする
qualityDropdown.value = QualitySettings.GetQualityLevel();
qualityDropdown.onValueChanged.AddListener(OnQualityChanged);
}
void OnDestroy()
{
qualityDropdown.onValueChanged.RemoveListener(OnQualityChanged);
}
private void OnQualityChanged(int index)
{
QualitySettings.SetQualityLevel(index);
Debug.Log("画質: " + QualitySettings.names[index]);
}
}
QualitySettings.names:プロジェクトにある画質の名前の一覧(テンプレートによって数が違うので、決め打ちせずにここから作ります)List<string>は、数を後から変えられる配列のようなものです。using System.Collections.Generic;が必要です
PlayerPrefsで設定を保存する
設定した値は、ゲームを終了すると元に戻ってしまいます。音量などの小さな設定は、PlayerPrefsで保存できます。
// 保存(キーの名前と値)
PlayerPrefs.SetFloat("Volume", 0.5f);
PlayerPrefs.SetInt("Fullscreen", 1);
PlayerPrefs.SetString("PlayerName", "勇者");
PlayerPrefs.Save();
// 読み込み(保存されていないときの値も指定する)
float volume = PlayerPrefs.GetFloat("Volume", 1f);
int fullscreen = PlayerPrefs.GetInt("Fullscreen", 1);
string playerName = PlayerPrefs.GetString("PlayerName", "Player");
- 保存できるのはint・float・stringの3種類。boolは1と0に変えて保存します
- セーブデータのような大きなデータには向いていません。設定の保存用と考えておきましょう
実践:設定画面を作ろう
ここまでの部品を1つの設定画面にまとめて、設定を保存できるようにしてみましょう。
UIの準備
Canvas
└── SettingsPanel (Panel)
├── NameInputField (Input Field - TextMeshPro)
├── VolumeSlider (Slider)
├── VolumeText (Text - TextMeshPro)
├── FullscreenToggle (Toggle)
├── QualityDropdown (Dropdown - TextMeshPro)
└── ResetButton (Button - TextMeshPro)
UIの並べ方は、9-6の記事で紹介するVertical Layout Groupを使うと、きれいに縦にそろえられます。
スクリプト
「SettingsMenu」という名前でスクリプトを作り、SettingsPanelにアタッチします(上で作った部品ごとのスクリプトは使わず、この1つにまとめています)。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class SettingsMenu : MonoBehaviour
{
[SerializeField] private TMP_InputField nameInputField;
[SerializeField] private Slider volumeSlider;
[SerializeField] private TMP_Text volumeText;
[SerializeField] private Toggle fullscreenToggle;
[SerializeField] private TMP_Dropdown qualityDropdown;
[SerializeField] private Button resetButton;
void Start()
{
qualityDropdown.ClearOptions();
qualityDropdown.AddOptions(new List<string>(QualitySettings.names));
LoadSettings();
nameInputField.onEndEdit.AddListener(OnNameChanged);
volumeSlider.onValueChanged.AddListener(OnVolumeChanged);
fullscreenToggle.onValueChanged.AddListener(OnFullscreenChanged);
qualityDropdown.onValueChanged.AddListener(OnQualityChanged);
resetButton.onClick.AddListener(ResetToDefaults);
}
void OnDestroy()
{
nameInputField.onEndEdit.RemoveListener(OnNameChanged);
volumeSlider.onValueChanged.RemoveListener(OnVolumeChanged);
fullscreenToggle.onValueChanged.RemoveListener(OnFullscreenChanged);
qualityDropdown.onValueChanged.RemoveListener(OnQualityChanged);
resetButton.onClick.RemoveListener(ResetToDefaults);
}
private void LoadSettings()
{
nameInputField.text = PlayerPrefs.GetString("PlayerName", "Player");
volumeSlider.value = PlayerPrefs.GetFloat("Volume", 1f);
fullscreenToggle.isOn = PlayerPrefs.GetInt("Fullscreen", 1) == 1;
qualityDropdown.value = PlayerPrefs.GetInt("Quality", QualitySettings.GetQualityLevel());
// 読み込んだ値を、ゲームにも反映する
ApplyVolume(volumeSlider.value);
Screen.fullScreen = fullscreenToggle.isOn;
QualitySettings.SetQualityLevel(qualityDropdown.value);
}
private void OnNameChanged(string playerName)
{
PlayerPrefs.SetString("PlayerName", playerName);
PlayerPrefs.Save();
}
private void OnVolumeChanged(float value)
{
ApplyVolume(value);
PlayerPrefs.SetFloat("Volume", value);
PlayerPrefs.Save();
}
private void OnFullscreenChanged(bool isOn)
{
Screen.fullScreen = isOn;
PlayerPrefs.SetInt("Fullscreen", isOn ? 1 : 0);
PlayerPrefs.Save();
}
private void OnQualityChanged(int index)
{
QualitySettings.SetQualityLevel(index);
PlayerPrefs.SetInt("Quality", index);
PlayerPrefs.Save();
}
private void ApplyVolume(float value)
{
AudioListener.volume = value;
volumeText.text = "音量: " + Mathf.RoundToInt(value * 100) + "%";
}
private void ResetToDefaults()
{
// 値を変えると、それぞれのonValueChangedも呼ばれて保存される
nameInputField.text = "Player";
OnNameChanged("Player");
volumeSlider.value = 1f;
fullscreenToggle.isOn = true;
qualityDropdown.value = QualitySettings.names.Length - 1;
}
}
このスクリプトのポイント:
- Startで読み込んでから、イベントを登録する:先に登録すると、読み込んだ値を入れたときにも保存処理が呼ばれてしまうため
- 値が変わるたびに保存する:「適用」ボタンを押さなくても、変えた瞬間に保存されます
- OnDestroyで登録を外す:オブジェクトが消えたあとに呼ばれないようにする片付けです
スライム設定画面って、部品が多くてInspectorの設定だけで疲れる・・・



Panelでまとめて、名前をちゃんと付けておくと、ドラッグ&ドロップのときに迷わないよ!
よくあるエラーと対処法
エラー:The name ‘AudioSettings’ is ambiguous(あいまいです)
- 原因:自分で作ったクラスの名前が、Unityに最初からあるクラス(AudioSettings、GraphicsSettingsなど)と同じ
- 対処法:VolumeSliderやSettingsMenuのように、ほかと重ならない名前にする
エラー:Dropdownの選択肢が表示されない
- 原因:Optionsが空、またはTemplate(子のオブジェクト)を消してしまった
- 対処法:Optionsを確認する。Templateを消した場合は、Dropdownを作り直す
エラー:日本語を入力すると□になる
- 原因:Input Fieldの中のText(TMP)が英語用のフォントのまま
- 対処法:Text AreaのText(TMP)とPlaceholderのFont Assetを、日本語のフォントアセットにする(9-3の記事)
エラー:Toggleがラジオボタンのように連動しない
- 原因:Toggle Groupが設定されていない
- 対処法:空のオブジェクトにToggle Groupを付け、各ToggleのGroupにそれを設定する
エラー:Input Fieldに入力できない
- 原因:EventSystemがない、またはInteractableが外れている
- 対処法:シーンにEventSystemがあるか確認する(9-1の記事)
まとめ
- Input Field:
TMP_InputField、確定したときはonEndEdit - Slider:
valueとonValueChanged(floatが渡される) - Toggle:
isOnとonValueChanged(boolが渡される) - Dropdown:
TMP_Dropdown、valueとonValueChanged(番号が渡される) - 設定の保存はPlayerPrefs
- クラス名は、Unityのクラスと重ならないように付ける
次のステップ
リストが長くなってスクロールさせたいとき、部品をきれいに並べたいときの方法を学びましょう:
コメント
コメント一覧 (1件)
[…] 入力系のUIを作ろう:InputField・Slider・Toggle・Dropdown […]