こんにちは、ばいおです。
以前Unityで作ったSAPクイズゲームを少しずつ改良していっているのですが、先日新しく入力式クイズモードを追加しました。
せっかくなので、今回はその作り方について記事にしてみました。
ちなみにゲームのイメージはこんな感じです(動画です)。
ゲームは以下リンク先よりプレイできます。是非やってみてください!(随時更新中)
https://unityroom.com/games/sapquiz
実際にゲームやってみての感想や改善点などがありましたら、ゲームリンク先のUnityroomにコメントを残せるので、是非コメントしてください!泣いて喜びます!
(ランキング機能も実装したので是非登録してくださいまし!)
また、クイズゲーム制作についての記事は↓にまとめていますので、あわせてご参照ください!
私がゲーム作成にあたり、勉強に使用したUnity本はコチラ↓
実際にサンプルゲームを作成しながら楽しく学べるので、オススメです!
入力式クイズ作成にあたって追加した機能
クイズの答えを入力するフォーム
入力式クイズに必要なものは何か、と考えてまず思いついたのが、クイズの答えを入力するフォームでした。
Unityには入力フォームにお誂え向きのUIがありまして、それが「InputField」です。
(赤枠で囲まれた部分です)
UI「InputField」を用意して、そこに入力されたテキストと、CSVファイルで読み込ませた問題の答えとを突合することで、正誤判定ができます。これで、入力式クイズの土台は作成できました!
以下の侍エンジニアさまの記事を参考にしています。
最初から入力フォームにフォーカスする
入力フォームを作ったはいいものの、答えを入力する時に、いちいち入力フォームをクリックしなきゃいけないのは、面倒ですよね。
なので、最初から入力フォームに答えを入力できるようカーソルが合っていればいいのに、、と思って方法を探してみたところ、ばっちりありました。
結論、以下のソースを書けば良いです。(※inputFieldはUIのInputFieldです)
inputField.ActivateInputField();
以下のもぎさまの記事を参考にしています。
小文字⇒大文字への変換
SAPのトランザクションコードって、小文字・大文字関係なくどちらでも認識されますよね。
ならば当クイズでも同じ仕様にしなくてはと考え、入力フォームに入力されたテキストは全て大文字へと変換されるような仕様にしています。
この仕様は、ToUpperメソッドを使うことで実現できました。
以下のITsakuraさまの記事を参考にしています。
エンターキーを押すと次の画面に遷移
入力式クイズのプロトを作って気になったのが、画面遷移でした。
4択式クイズでは、マウスクリックでクイズの答えを選択するため、次の画面へ遷移するときもマウスを使うことに違和感はなかったのですが、入力式クイズだと話は変わります。
入力式クイズでは、答えはキーボードで入力するので、次の画面へ遷移するときにマウスクリックするとなると、キーボードとマウス両方使用しなくてはいけないですね。
これはかなり操作性が悪いなと思いました。
(そもそも、SAP実機でも、トランザクションコードを入力してエンターキー押せば画面遷移しますしね!)
なので、エンターキーを押せば、次の画面へ遷移するボタンをクリックしたのと同じ扱いになるような機能を実装しました。
ゲーム中にエンターキーが押されたと認識させるためには、以下のソースを追加すればよいです。
if(Input.GetKeyDown(KeyCode.Return))
{
エンターキーを押すことで行いたい処理
}
Input.GetKeyDownでキーの押下、KeyCode.Returnがエンターキーの意味ですね。
Input.GetKeyというのもあるようですが、こちらはキーを押している間ずっと発動されてしまうようなので、今回は使用しませんでした。
以下のかめくめさまの記事を参考にしています。
続いて、次の画面に遷移するボタンをクリックしたことにする処理についてです。
こちらは、Button(UI)のonClickイベントをInvokeで呼び出すことにより実現できました。
以下のわたぶろぐさまの記事を参考にしています。
エンターキーの押下を認識するソースと、ボタンが押されたことになる処理を行うソースを合わせると、以下のようになりますね。
if(Input.GetKeyDown(KeyCode.Return))
{
push_button.onClick.Invoke();
}
入力式クイズ作成にあたり追加したソースコード
何かの役に立つかなーと思い、入力式クイズの作成にあたり追加したソースコードを載せます。
ご参考までに。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Linq;
public class inputquestion : MonoBehaviour
{
TextAsset csvFile; // CSVファイル
public static List<string[]> csvDatas = new List<string[]>(); // CSVの中身を入れるリスト;
public static List<int> qnumber = new List<int>(); // 出題番号リスト;
public int csvrow; // CSVファイルの行数
public static string answer; // クイズの答え
public static string genre; //ジャンル
private int k = 0; //配列の変数
private int qransu = 0; // 出題する問題の行
void Start()
{
int qcount = gamestart.getqCount();
if(qcount == 0) // 1問目の時のみ以下処理を行う
{
clearlist();
csvFile = Resources.Load("inputquiz") as TextAsset; // Resouces下のCSV読み込み
StringReader reader = new StringReader(csvFile.text);
while (reader.Peek() != -1) // reader.Peaekが-1になるまで
{
string line = reader.ReadLine(); // 一行ずつ読み込み
csvDatas.Add(line.Split(',')); // , 区切りでリストに追加
csvrow++; // CSVファイルの行数カウント
}
for (int j = 1; j <= csvrow-1; j++)
{
qnumber.Add(j); // CSVファイルの行をリストに追加(1行目は除外)
}
qnumber = qnumber.OrderBy ( a => System.Guid.NewGuid () ).ToList (); // 読み込んだリストをシャッフル
csvrow = 0; //変数初期化
}
qransu = qnumber[qcount]; // シャッフルされたリストを問題数順に取得
QuestionLabelSet();
AnswerLabelSet();
QuestionNumSet();
GenreSet();
// InputFieldコンポーネントを格納
InputField inputField = GameObject.Find("Canvas/InputField").GetComponent<InputField>();
//InputFieldにフォーカスする
inputField.ActivateInputField();
}
void Update ()
{
// エンターキー押下の認識
if(Input.GetKeyDown(KeyCode.Return))
{
buttonpush();
}
}
private void QuestionLabelSet()
{
csvDatas[k] = csvDatas[qransu]; // CSVの"qransu"行目の問題を取得
Text qLabel = GameObject.Find("Canvas/Question").GetComponent<Text> ();
qLabel.text = csvDatas[k][0];
}
private void AnswerLabelSet()
{
answer = csvDatas[k][1];
}
private void QuestionNumSet()
{
int qCount = gamestart.getqCount() + 1;
Text qnumLabel = GameObject.Find("Canvas/QuestionNum").GetComponentInChildren<Text> ();
qnumLabel.text = "問題 " + qCount.ToString() + "/10";
}
private void GenreSet()
{
genre = csvDatas[k][2];
Text genreLabel = GameObject.Find("Canvas/Genre").GetComponentInChildren<Text> ();
genreLabel.text = "ジャンル:" + genre;
}
public static void buttonpush()
{
// UIボタンの取得
Button pushbutton = GameObject.Find("Canvas/ansbutton").GetComponentInChildren<Button>();
// UIボタンの押下
pushbutton.onClick.Invoke();
}
}
おわりに
今回は、Unityでの入力式クイズの作り方について記載しました。
記事を読んでもらえたらわかる通り、基本やりたいことを思いついたらググってそれを使う、といったことを繰り返してます。
欲しい情報がネットで検索したら簡単に無料で手に入るって本当にすごい世の中ですよね。
そして、その情報を提供してくださる先人の方々に感謝です。
まだまだ改良していく予定なので、また大きめの改修をしたら記事にしようと思います。
最終的には、SAP初学者の勉強に有用なものが作れたらなあと思います。
自分でプログラム書いて物作りするのって本当に楽しいですね!
ここまで読んでいただきありがとうございました。