脱出ゲームに欠かせないパスワード入力のギミックですが、過去にこんな投稿をしています。
上記の記事ではUnityのUI上のパネルにパスワード入力パネルを作りました。
今回はパネルを使わずによりリアルなパスワード入力パネルを作ってみました。

これを作る上で思ったのが3DのTextMeshPro(TMP)がとても便利だということです。
1つ1つのボタンはPrefabにして、ボタンの中にTMPを入れて、文字を表示するようにしています。
ボタンには以下のスクリプトをアタッチします。
using TMPro; using UnityEngine; public class EnglishButton : MonoBehaviour { [SerializeField] TMP_Text englishText; public string alphabet; // Start is called before the first frame update void Start() { englishText.text = alphabet; } public void OnClickThis() { Debug.Log(alphabet); EnglishPassword.instance.buttonInput(alphabet); } }
自分で設定したい文字列をpublicにおけばいつでもボタン上の英字が変えられるのが便利です。
ボタン入力がされた時に呼ばれる関数は以下の通り。
public void buttonInput(string alphabet) { //入力時点で4文字入力されていたら初期化する。 if (index == 4) { resetInput(); } //入力されたアルファベットを保存し、表示用テキストにも追加する input[index] = alphabet; displayText.text += alphabet; index++; }
文字数(index)が4つだったら初期化し、正解チェック用の配列と表示用のテキストに入力された文字を入れるようにしています。
正解チェックは以下のようにしています。
public bool checkPassword() { // 1文字ずつ順番にチェックし1つでも間違いがあればFalseを返す。 for (int i = 0; i < collect.Length; i++) { if (input[i] != collect[i]) { return false; } } return true; }
1つでも違っていた時点でfalseを返し、全部合っていたらtrueを返すという実装をすることで、コードが綺麗になりました。
おわり。
親子関係と全体のコード
ヒエラルキーは以下のようになっています。親オブジェクトにパネル(板)、子オブジェクトにボタンを配置しています。

親オブジェクトにアタッチしているスクリプトは以下の通り。
using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.Events; public class EnglishPassword : MonoBehaviour { // アルファベットの入力を入れる配列 [SerializeField] string[] input; // 正解のアルファベットを入れる配列 [SerializeField] string[] collect; // 入力inputの添字 int index; // 正解時に発生させるイベント public UnityEvent someEvent; // inputの内容を表示するためのテキスト。TextMeshProを利用。 [SerializeField] TMP_Text displayText; // Start is called before the first frame update void Start() { //開始時に初期化をする resetInput(); } public void buttonInput(string alphabet) { //入力時点で4文字入力されていたら初期化する。 if (index == 4) { resetInput(); } //入力されたアルファベットを保存し、表示用テキストにも追加する input[index] = alphabet; displayText.text += alphabet; index++; } public void resetInput() { //表示用テキストとinput配列を空(null)にする displayText.text = null; index = 0; for (int i = 0; i < input.Length; i++) { input[i] = null; } } public void isClear() { // OKボタンが押された時の処理 // 正解チェックを行いイベントを発生させる if (checkPassword()) { someEvent.Invoke(); } resetInput(); } public bool checkPassword() { // 1文字ずつ順番にチェックし1つでも間違いがあればFalseを返す。 for (int i = 0; i < collect.Length; i++) { if (input[i] != collect[i]) { return false; } } return true; } }
子オブジェクトにアタッチするスクリプトは以下の通りとなります。
using TMPro; using UnityEngine; public class EnglishButton : MonoBehaviour { [SerializeField] TMP_Text englishText; public string alphabet; // Start is called before the first frame update void Start() { englishText.text = alphabet; } public void OnClickThis() { transform.GetComponentInParent<EnglishPassword>().buttonInput(alphabet); } }