今回は謎解きゲームで使いそうな数値入力UIの作成方法を解説します。
目次
数値入力UIの作成方法
素材データのダウンロード
今回は日本語テキストを使用したいので、日本語フォントをプロジェクトに追加しておきます。

Themeリソースの作成
日本語フォントを使用するために Theme リソースを作成します。ファイルシステムを右クリックして「新規リソース…」を選びます。

Themeリソースを作成します。

リソースの名前を指定します。ここでは「default_theme.tres」としました。

作成した Themeリソースをダブルクリックして、インスペクターから「Default Font > [空]」をクリックして「新規 DynamicFont」を選びます。

作成した DynamicFont をクリックするとフォントの設定が表示されるので「Font > FontData > [空]」をクリックして「読み込み」を選びます。

プロジェクトに追加した日本語フォント “mplus-1c-regular.ttf” を開きます。

これで日本語フォントを設定できたので「保存」をクリックしてセーブしておきます。

数値入力のパーツのシーンを作成する
次に数値入力のパーツのシーンを作成します。
コンテナを使ってUI部品をまとめたいので「+その他のノード」をクリックします。

作成するUIノードは「VBoxContainer」となります。これは縦方向にUIをまとめるコンテナとなります。

UIノードを作成したらノード名を「NumberInputSimgle」とリネームしておきます。

ボタンと数値テキストを表示する
次に「Button」ノードを追加します。

作成したら名前を「ButtonUp」に変更します。

このボタンは上向きの矢印ボタンとするためです。
次に数値をテキストとして表示するために「Label」を追加します。ただいったんルートノードを選択しないと “ButtonUp” の下の階層に作られてしまうので、「NumberInputSimgle」を選択してから作成するとよいです。


Labelノードは特にリネームせずに「NumberInputSimgle」を選択して、下向きのボタンノード (Button) を作成します。


作成したボタン名は「ButtonDown」にリネームします。

Themeリソースを設定する
各UIで日本語を表示できるように Themeリソースを設定します。
このとき Shiftキーを押しながらノードを選択するとまとめて選択でき、まとめて Themeリソースを割り当てることができます。

選択したらインスペクターから「Theme > Theme > [空]」をクリックして、「読み込み」を選びます。

先ほど作成した Themeリソース “default_theme.tres” を開きます。

これで日本語フォントが各UIで使用できるようになったので、それぞれの「Text」に以下の文字を設定します。
- ButtonUp: ▲ (上向きの三角)
- Label: 0
- ButtonDown: ▼ (下向きの三角)

これで数値入力UIっぽいものができたのですが、文字が左揃えになっているので、”Label”ノードを選択して、インスペクターから「Label > Align」の値を「Center」にして “中央揃え” に変更しておきます。

補足:見た目を良くしたい場合
今回は楽をするために “Button”ノードを使用し、日本語フォントで上下の三角ボタンを作成しましたが、「TextureButton」を使用すると Texture からボタンの見た目を画像に変更できます。

よりクオリティを上げたい場合はこちらのUIノードを使用するのが良いと思います。
上下ボタンの入力を処理する
次に上下ボタンの入力を処理します。
その前にまずは「Ctrl+S (Cmd+S)」でシーンを「NumberInputSimgle.tscn」として保存します。

保存できたら “NumberInputSimgle” ノード(ルートノード) にスクリプトをアタッチします。
extends VBoxContainer
export var min_value = 0 # 最小値
export var max_value = 9 # 最大値
export var value = 0 # 現在の値
onready var label = $Label
func _process(_delta: float) -> void:
# ラベルに数値を反映する
label.text = str(value)
ここで扱う場合には1桁の数値なので「0〜9」の数値を入力できるとします
次に “ButtonUp” を選び pressed() シグナルを追加します。シグナルのコードは以下のとおりです。
func _on_ButtonUp_pressed() -> void:
# 上ボタンを押した場合
# 値を減算する
value -= 1
if value < min_value:
value = max_value
上ボタンは値が増加しそうな気がするのですが、私の好みで値が減少するようにしました。違和感がある場合は増加でも良いと思います。
“ButtonDown” にも pressed() シグナルを追加します。シグナルのコードは以下のとおりです。
func _on_ButtonDown_pressed() -> void:
# 下ボタンを押した場合
# 値を加算する
value += 1
if value > max_value:
value = min_value
では実行して動作を確認します。

念のため、NumberInputSimgle.gd スクリプトのコード全文をのせておきます。
extends VBoxContainer
export var min_value = 0 # 最小値
export var max_value = 9 # 最大値
export var value = 0 # 現在の値
onready var label = $Label
func _process(_delta: float) -> void:
# ラベルに数値を反映する
label.text = str(value)
func _on_ButtonUp_pressed() -> void:
# 上ボタンを押した場合
# 値を減算する
value -= 1
if value < min_value:
value = max_value
func _on_ButtonDown_pressed() -> void:
# 下ボタンを押した場合
# 値を加算する
value += 1
if value > max_value:
value = min_value
余談: 文字入力を可能にしたい場合
今回は解説しませんが、数値入力ではなく、文字入力(文字選択)を可能にしたい場合は「選択可能な文字をリストにする」方法で実装できます。
以下実装例です。
# 文字を選ばせる入力UIの実装例
extends VBoxContainer
export var value = 0 # 現在の値
var table = ["あ", "い", "う", "え", "お"]
onready var label = $Label
func _process(_delta: float) -> void:
# ラベルにvalueに対応するテーブルの文字を反映する
label.text = table[ value ]
4桁の数値入力を行うUIを作成する
1桁の数値入力であればこれで良いのですが、たいていはある程度の桁数の数値入力が必要になると思います。
そこで4桁の数値入力をできるUIを作成してみます。
ルートノード(Mainシーン)の作成
コントロールノードを新規作成します。

ノード名は「Main」に変更して、シーンとして保存(Main.tscn)しておきます。

そしてスクリプト (Maingd) をアタッチしておきます。
extends Control
まだ何も実装しないので中身は型の定義のみで良いです。
HBoxContainerを作成する
複数の桁数を管理するために “HBoxContainer” ノードを作成します。

これは UIを横並びに整列するUIコンテナノードです。
そして作成した HBoxContainer に “NumberInputSimgle.tscn” をドラッグ&ドロップで追加していきます。

うまく追加できない (HBoxContainerの直接の子ノードにならない) 場合は、作成したノードをドラッグ&ドラップで調整をします。
入力判定確認用のラベルを作成する
入力判定確認用に2つのラベルを追加します。

それぞれ日本語フォントのテーマ(default_theme.tres) を設定しておいてください。
そして Label ノードの Text には「99かける99は?」と入力し、Label2ノードの Textには「入力した値」と設定して良い感じの位置に調整しておきます。

入力判定を行うボタンを追加する
次に「Button」ノードを追加します。

Themeには “default_theme.tres” を設定して日本語フォントを使えるようにしておき、Textには「決定」と設定してわかりやすい場所に移動させます。
そしてButtonの pressed() シグナルを追加し、Main.gd スクリプトを以下のように実装します。
extends Control
onready var label = $Label2
onready var numbers = $HBoxContainer
func _ready() -> void:
pass # Replace with function body.
func _on_Button_pressed() -> void:
var num = 0
# 逆順で合計値を求める
var digit = numbers.get_child_count() - 1
for child in numbers.get_children():
var v = child.value
num += v * pow(10, digit)
digit -= 1
label.text = "入力した値: %d"%num
if num == 9801:
label.text = "正解!"
HBoxContainerのget_child() で上から順に数値入力(NumberInputSingle)が取得できるので、逆順(千の位→百の位→十の位→一の位)で合計値を計算します。
pow() を使うと10の指数(桁数)からその桁に対応する値を求めることができるので便利です。
では実行して動作を確認します。

99×99 は 9801 なので、”9801″ を入力すると正解となります。
完成プロジェクト
今回作成したプロジェクトファイルを添付しておきます。