今回はUnityで簡単なタイピングソフトを作成したいと思います。
ローマ字入力のタイピングソフトですね。
簡単なタイピングソフトとは『機能的にシンプルなタイピングソフト』であり『タイピングソフトが簡単に作れる』、『簡単にタイピングソフトを作る』という事ではないのでご了承ください(^_^;)
以前の記事

でキーボードからの入力を判定する事をやったのでその実践的な使い方のサンプルとしてタイピングソフトを作ってみます。
タイピングソフトの概要
今回作成するのはローマ字入力のタイピングソフトになります。
問題をいくつか用意しておきタイピングに成功したら次の問題をランダムに出題するようにします。
1文字毎にタイピングに成功したか失敗したかを計測し、正解率等をUIで表示するようにします。
難しい機能は搭載しないので作成した問題をひたすら入力して終わる(実際は終わりがない・・・・)だけになりますね・・・・(^_^;)
タイピングソフトのUIを作成する
まずは問題を出力する部分、正解数、失敗数、正解率を表示するUIを作成していきます。
ヒエラルキー上で右クリック→UI→Canvasを選択し、名前をTypingSoftに変更します。
TypingSoftの子要素に右クリック→UI→Panelを2つ作成し、名前をInputPanelとDataPanelとし、それぞれサイズを調整します。
それぞれのパネルの子要素に右クリック→UI→Textを選択し名前をQuestionJ、QuestionR、Input、Correct Answer、Mistake、Correct Answer Rateとします。
↑のような階層を作成します。
↑が作成したタイピングソフトのUIの配置になります。
キャンバスであるTypingSoftのCanvas Scalerを変更します。
UI Scale ModeをScale With Screen Sizeに変更します。
Screen Match ModeはMatch Width or Heightにします。
MatchがWidthになっているので横幅に応じてUIのサイズが変更されます。
これでタイピングソフトのUIが完成しました。
タイピングソフトの機能を作成する
タイピングソフト用のUIが完成したのでタイピングソフトの機能を作成していきましょう。
まずはタイピングソフトの機能全般を行うTypingSoftスクリプトを作成しTypingSoftゲームオブジェクトに設定してください。
問題を作成し出力する
TypingSoftスクリプトに問題文を作成し、問題の中からランダムに1つを選んでテキストに出力する処理を作成していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | using UnityEngine; using System.Collections; using UnityEngine.UI; public class TypingSoft : MonoBehaviour { // 問題の日本語文 private string[] qJ = {"問題", "テスト", "タイピング", "かめくめちゃん" }; // 問題のローマ字文 private string[] qR = {"monndai", "tesuto", "taipinngu", "kamekumechann" }; // 日本語表示テキスト private Text UIJ; // ローマ字表示テキスト private Text UIR; // 日本語問題 private string nQJ; // ローマ字問題 private string nQR; // 問題番号 private int numberOfQuestion; void Start () { // テキストUIを取得 UIJ = transform.Find("InputPanel/QuestionJ").GetComponent<Text>(); UIR = transform.Find("InputPanel/QuestionR").GetComponent<Text>(); // 問題数内でランダムに選ぶ numberOfQuestion = Random.Range(0, qJ.Length); // 選択した問題をテキストUIにセット nQJ = qJ[numberOfQuestion]; nQR = qR[numberOfQuestion]; UIJ.text = nQJ; UIR.text = nQR; } } |
まずは問題の日本語の配列とローマ字の配列を同じ並びで作成します。
問題の番号と配列の番号が一緒になるように作成していきます。
ローマ字の問題をもっと簡単に間違えず作成するにはひらがなと対応するローマ字の対応表を作成しておきそれを使ってローマ字を作成します。
例えば、最初の『問題』に対応するローマ字を作るなら『もんだい』というひらがな文を配列で作成しておき、
『も』→『mo』、『ん』→『nn』、『だ』→『da』、『い』→『i』
とひらがなからローマ字を作成し、それを連結してローマ字を表示するテキストUIに表示するようにします。
今回は割愛ということで・・・・。
UIJとUIRは問題を表示するテキストUIを設定するフィールドでtransform.Findを使って子要素から対応するテキストUIを探して設定しています。
その後Random.Rangeを使って問題数分の中から1つの値を取得し、その番号に対応する問題をテキストUIに表示しています。
問題を出力するメソッドを作る
問題はタイピングソフトスタート時だけに出力するわけではなく、1つの問題が打ち終わった時も同じように出力します。
その為、問題をランダムに選び出力するという処理をひとまとめにして問題を出力するメソッドにまとめてしまいましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | void Start () { // テキストUIを取得 UIJ = transform.Find("InputPanel/QuestionJ").GetComponent<Text>(); UIR = transform.Find("InputPanel/QuestionR").GetComponent<Text>(); // 問題出力メソッドを呼ぶ OutputQ(); } // 新しい問題を表示するメソッド void OutputQ() { // 問題数内でランダムに選ぶ numberOfQuestion = Random.Range(0, qJ.Length); // 選択した問題をテキストUIにセット nQJ = qJ[numberOfQuestion]; nQR = qR[numberOfQuestion]; UIJ.text = nQJ; UIR.text = nQR; } |
問題出力メソッドをOutputQにまとめ、次の問題を表示する時はこのOutputQを呼び出せば新しい問題が表示されるようにします。
問題をタイピングする機能
次は表示された問題のローマ字をキーボードから入力出来るようにし、正解の時は正解数のカウントとInputテキストに文字を表示し、失敗の時は失敗数のカウントと間違えた文字を別の色で表示します。
まずはキーボードからの入力と問題のローマ字が合っているかどうかの処理を追加していきましょう。
ローマ字の問題文の何文字目か?を表す変数indexOfStringを用意し正解時には数値を足していく事で次の文字を指すようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // 問題の何文字目か private int indexOfString; void Update() { // 今見ている文字とキーボードから打った文字が同じかどうか if (Input.GetKeyDown(nQR[indexOfString].ToString())) { // 正解時の処理を呼び出す Correct(); // 問題を入力し終えたら次の問題を表示 if (indexOfString >= nQR.Length) { OutputQ(); } } else if (Input.anyKeyDown) { // 失敗時の処理を呼び出す Mistake(); } } // タイピング正解時の処理 void Correct() { Debug.Log("正解"); } // タイピング失敗時の処理 void Mistake() { Debug.Log("失敗"); } // 正解率の計算処理 void CorrectAnswerRate() { Debug.Log("正解率計算"); } |
Input.GetKeyDownを使って現在見ているローマ字と打ったキーが同じかどうかを判定しています。
同じだった場合はCorrectメソッド、違った場合はMistakeメソッドを呼んでいます。
それぞれのメソッドでは正解と失敗という文字を表示しているだけで中身はこれから作成していきます。
正解時の処理Correctメソッドを呼んだ後に現在見ている文字列の番号が文字列の長さを超えた時は全ての文字を打ち終わったのでOutputQメソッドを呼んで次の問題を出力します。
Correctメソッドの実装
正解時の処理を行うCorrectメソッドの中身を実装していきましょう。
正解時には今入力した文字をInputテキストUIに出力し、ローマ字の問題の次の文字を指すようにし、正解率を計算します。
正解数を使いますのでフィールドの宣言等も追加しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | // 入力した文字列テキスト private Text UII; // 正解数 private int correctN; // 正解数表示用テキストUI private Text UIcorrectA; // 正解した文字列を入れておく private string correctString; void Start () { // テキストUIを取得 UIJ = transform.Find("InputPanel/QuestionJ").GetComponent<Text>(); UIR = transform.Find("InputPanel/QuestionR").GetComponent<Text>(); UII = transform.Find("InputPanel/Input").GetComponent<Text>(); UIcorrectA = transform.Find("DataPanel/Correct Answer").GetComponent<Text>(); // データ初期化処理 correctN = 0; UIcorrectA.text = correctN.ToString(); // 問題出力メソッドを呼ぶ OutputQ(); } // 新しい問題を表示する関数 void OutputQ() { // テキストUIを初期化する UIJ.text = ""; UIR.text = ""; UII.text = ""; // 正解した文字列を初期化 correctString = ""; // 文字の位置を0番目に戻す indexOfString = 0; // 問題数内でランダムに選ぶ numberOfQuestion = Random.Range(0, qJ.Length); // 選択した問題をテキストUIにセット nQJ = qJ[numberOfQuestion]; nQR = qR[numberOfQuestion]; UIJ.text = nQJ; UIR.text = nQR; } // タイピング正解時の処理 void Correct() { // 正解数を増やす correctN++; UIcorrectA.text = correctN.ToString(); // 正解率の計算 CorrectAnswerRate(); // 正解した文字を表示 correctString += nQR[indexOfString].ToString(); UII.text = correctString; // 次の文字を指す indexOfString++; } |
OutPutQメソッドでは問題を出力する前にテキストUI等を初期化する処理を入れておきます。
Correctメソッド内では正解数を増やしその後に正解率を計算してます。
タイピングが成功した場合は現在打っているローマ字をテキストに足しています。
文字を足した後に次の問題を見るようにindexOfStringを足しています。
ここまでの機能を確認してみましょう。
↑のようにタイピングに成功すると文字が表示され正解数が増えているのが確認出来ます。
Mistakeメソッドの実装
次は失敗した時の処理を行うMistakeメソッドを実装していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // 失敗数 private int mistakeN; // 失敗数表示用テキストUI private Text UImistake; void Start () { // テキストUIを取得 UIJ = transform.Find("InputPanel/QuestionJ").GetComponent<Text>(); UIR = transform.Find("InputPanel/QuestionR").GetComponent<Text>(); UII = transform.Find("InputPanel/Input").GetComponent<Text>(); UIcorrectA = transform.Find("DataPanel/Correct Answer").GetComponent<Text>(); UImistake = transform.Find("DataPanel/Mistake").GetComponent<Text>(); // データ初期化処理 correctN = 0; UIcorrectA.text = correctN.ToString(); mistakeN = 0; UImistake.text = mistakeN.ToString(); // 問題出力メソッドを呼ぶ OutputQ(); } // タイピング失敗時の処理 void Mistake() { // 失敗数を増やす(同時押しにも対応させる) mistakeN += Input.inputString.Length; UImistake.text = mistakeN.ToString(); // 正解率の計算 CorrectAnswerRate(); // 失敗した文字を表示 if (Input.inputString != "") { UII.text = correctString + "<color=#ff0000ff>" + Input.inputString + "</color>"; } } |
タイピングを失敗した時はそのフレームで入力した文字列Input.inputStringの文字数分を失敗数に換算出来るようにしています。
同時押し分を換算しないのであれば
1 2 3 | mistakeN++; |
という処理だけでも大丈夫です。
その後正解率の計算をし、今まで正解してきた文字列に今打った文字を赤色にしたものを足してInputに表示するようにしています。
Input.inputStringが空でない時だけUIにテキストを表示するようにします。
テキストの色を変更するにはタグを使用します。
colorに指定するのは#赤緑青透を16進数で表したものを指定します。
HTMLタグと同じですね、例えば赤色の文字にする場合は
<color=#ff0000ff>色を変える文字</color>
青色の文字にする場合は
<color=#0000ffff>色を変える文字</color>
となります。
タグと文字を同時に扱っているのでダブルクォーテーションと文字列とを連結しています。
↑のようにタイピング失敗時に間違えて打った文字が赤く表示されるようになりました。
CorrectAnswerRateの実装
最後に正解率を計算するCorrectAnswerRateメソッドを実装していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // 正解率 private float correctAR; // 正解率表示用テキストUI private Text UIcorrectAR; void Start() { // テキストUIを取得 UIJ = transform.Find("InputPanel/QuestionJ").GetComponent<Text>(); UIR = transform.Find("InputPanel/QuestionR").GetComponent<Text>(); UII = transform.Find("InputPanel/Input").GetComponent<Text>(); UIcorrectA = transform.Find("DataPanel/Correct Answer").GetComponent<Text>(); UImistake = transform.Find("DataPanel/Mistake").GetComponent<Text>(); UIcorrectAR = transform.Find("DataPanel/Correct Answer Rate").GetComponent<Text>(); // データ初期化処理 correctN = 0; UIcorrectA.text = correctN.ToString(); mistakeN = 0; UImistake.text = mistakeN.ToString(); correctAR = 0; UIcorrectAR.text = correctAR.ToString(); // 問題出力メソッドを呼ぶ OutputQ(); } // 正解率の計算処理 void CorrectAnswerRate() { // 正解率の計算 correctAR = 100f * correctN / (correctN + mistakeN); // 小数点以下の桁を合わせる UIcorrectAR.text = correctAR.ToString("0.00"); } |
例によって追加分だけの記述になります。
CorrectAnswerRateメソッド内では正解数と失敗数を使ってfloat型の正解率を計算しています。
100 × 正解数 / (正解数と失敗数)
で正解率を計算しています。
正解率を表示する時には小数点以下の桁を2桁にする為ToStringの引数に”0.00″を書き小数点以下は2桁の表示にしています。
これで正解率を計算し表示する関数CorrectAnswerRateの実装が終了しました。
Input入力のTip
キーボードを押しっぱなしにしUpdateメソッドでInput.anyKeyで連続でそのキーを取得する事が出来ますが、1フレームだけ判定し、一旦入力をリセットしたいこともあります。
そんな時は、Input.ResetInputAxesメソッドを使用すると、そのフレームでの入力がリセットされるので、Input.GetKeyを使ってもすぐに次の判定をされる事がありません。
例えば以下のようにするとキーボードを押しっぱなしにするとずっとaがコンソールに出力されますが、
1 2 3 4 5 6 7 | void Update() { if(Input.anyKey) { Debug.Log("a"); } } |
以下のようにInput.ResetInputAxes()を追加するとキーボードを押しっぱなしでも最初の文字が入力されてから一定時間次の文字が入力されません。
1 2 3 4 5 6 7 8 | void Update() { if(Input.anyKey) { Debug.Log("a"); Input.ResetInputAxes(); } } |
最後に作成したタイピングソフトを確認してみます。
タイピングソフトの改善点
今回作成したタイピングソフトは機能的に全然足りてません。
ローマ字の問題をひらがなから作成したり、『ちゃ』を入力する時に『cha』、『cya』と両方の入力に対応したりといった機能も取りつけると良さそうですね。
しかし1つの記事内でこれだけの物が出来た事を考えれば、タイピングオブザデッドみたいなタイピングゲームを作るのも十分可能ですね(^_^)v
本当は結構大変だけど・・・・(T_T)/~~~