Unityでタイピングゲームを作ってみる

はいどーもこんにちはフリーランスプログラマ(予定)のツミオです。
みなさんUnityってますか?
僕は寝ても覚めてもUnityをいじっています。

本日は「Unityでタイピングゲームを作ってみよう」という感じのお話です。

タイピングゲームとは

スマホ世代の方には馴染みが薄いかもしれませんが、タイピングゲームとはキーボードでの文字入力速度を競う遊びです。
有名なのはe-typingというサイトではないでしょうか。
僕のハイスコアは628点ですが、恐らくそこそこタイプ速度に自信がある人でも「タイピングゲームなにそれ?」というレベルの方なら300点前後かなと思います(数年前の若かりし頃の記録なので、今はもっと遅いです)。
ゲームなんで当然のことながら点数を上げるコツ(出題される単語を覚えるとか)がありますが、基本的にはタイプ速度が早く・正確であることが求められます。
1秒間に10打は当たり前の世界で、早い人になると20打近く打つんじゃないでしょーか。

タイピングゲームの実装を考える

さてここからが本題です。
タイピングゲームと一口に言っても、色々なものが考えられますよね。

・言語は? 英語か? 日本語か?
・日本語なら、ローマ字入力なのか? かな入力なのか?
・ローマ字入力なら多くの入力バリエーションがあるが、どれに対応するのか? あるいは全てに対応するのか?
・そして、どのようなゲーム性をもたせるのか?

それぞれの項目について見ていきましょう。

言語について

言語は英語か日本語かを考えていますが、当然別の言語でもOKです。
が、僕は英語と日本語以外だとかろうじて中国語のピンインが多少読める程度なので、ここでは英語と日本語だけに限定します。

まず英語。
これは簡単です。
キーボードに入力された文字をそのまま逐次(プレイヤーがタイプするたび)あるいは一括(すべての文字が入力されてから)で受け取ればよいだけです。
強いて問題を挙げるなら、イギリス英語とアメリカ英語でスペルが変わることがあることでしょうか。
例えばlicenceかlicenseかなどです。
これらに対応するには、開発者が英語という言語に精通している必要があるでしょう。

次は日本語です。
日本語の場合、考えられる入力方式は「逐次判定」「一括判定」のいずれかです。
先ほどもちょろっと書いた通り、逐次判定はプレイヤーがタイプするたびに判定します。
少しややこしい問題があるので、こちらはあとで詳しく書きます。

一括判定のタイプでかつ「完全に正解している場合のみ正解する」なら、誰でも実装方法を思いつきますよね(「不完全な文字列でも部分的に正解とする」処理を加えるなら、それなりに難しくなることが予想されます。正規表現を使って判定かなあ)。
全ての文字の入力を確認してから、その文字と正解の文字を比較します。
比較した結果、正しければ正解とします。間違っていたら、NGの処理をします。
これだけです。
バリエーションは「ローマ字で結果を受け取る」「かな文字で結果を受け取る」「漢字やカナを含む全ての文字で結果を受け取る」あたりが考えられるでしょーか。
僕が見た感じでは「漢字やカナを含む全ての文字で結果を受け取る」タイプが多いんじゃないでしょーか。

ローマ字入力か、かな入力か

次の問題は「ローマ字入力」か「かな入力」か、あるいは「どちらも許可する」のかどうかです。
このとき問題になるのは、やはり逐次入力のタイプです。
なぜなら、一括判定のタイプの場合、ローマ字入力タイプなら「ローマ字で結果を受け取る」「かな文字で結果を受け取る」「漢字やカナを含む全ての文字で結果を受け取る」のどれでも問題ありませんし、かな入力タイプなら「ローマ字で結果を受け取る」に対応させないだけで処理が済むからです。

逐次入力のタイプの場合、ローマ字のキーの位置と、かな入力のキーの位置は全く違います。
つまり、別々の処理が必要になるのです。
ローマ字入力なら「一つのアルファベットごとに判定」しますし、かな入力の場合は「一つのかな文字ごとに判定」することになるでしょう。
どちらの実装が簡単かなーと言えば、恐らくかな入力です。
理由は次の節で説明します。

ローマ字入力のバリエーション

さて、あなたは「逐次判定タイプ」の「ローマ字入力」に対応させたいとしました(一般的なタイピングゲームはほとんどこれだと思います)。
このとき問題になるのは「一つのかな文字に対して、複数のローマ字が可能であること」です。

例えば「しゃ」という文字を考えてみてください。
「sya」が真っ先に思い浮かびますね。他には「silya」「sixya」「cixya」「cilya」も可能です(c系に関しては意見がある方もいるでしょうが、「僕の環境では問題なくタイプできた=利用する人がいる可能性があるので対応すべき」というのが僕の考えです)。
かな入力なら「し」と「ゃ」という別々の文字で考えればよかったはずなのに、ローマ字入力では入力可能な表現が5種類もあるのです!
これは複雑ですね。

考えられる対応策は以下の通りです。

・あらゆる入力形式に対応
 →もっとも理想的ですが、実装が難しいです。
・オプションで設定した項目のみに対応
 →この形式のタイピングゲームはよく見かけますよね。「あらゆる入力形式に対応」とは比較にならないほど実装が簡単ですが、恐らく多くのタイパーはこの手のゲームを嫌うでしょう(多くの歴戦のタイパーは「最適化」という技術を使うため)。
・ユーザーが入力形式を定めることはできない
 →プログラミングの練習だったらいいんじゃないすか(ハナホジ)

オプションで設定した項目のみに対応させるのは簡単なので、ここでは「あらゆる入力形式に対応」させる場合を考えてみましょう。

あらゆる入力形式に対応させる方法

あらゆる入力形式に対応させるには、以下の2つを念頭に置かなければなりません。

・一つの文字に対して複数の入力可能形式があること
・一つの文字の入力可能形式は動的に変化すること

一番目は先ほどの節でも書いたことですね。
「か」という文字なら「ka」でも「ca」でも入力可能でなければなりません。

二番目の問題も重要です。
例えば「このよにうまれんおちるしぃたっけせんせいさん」という言葉を考えてみてください。
「ko(co) no yo ni u ma re」まではいいですね。
つぎの「ん」はどうでしょうか。
「ん」は「n」か「nn」の両方が入力可能であるはずですが、これは「次の文字に依存」します。
つまり次の文字が母音もしくは「n」だったならば、「ん」の入力可能文字は「nn」のみなのです。
なぜなら、「n」のみ入力したあとに母音がくると「あいうえお」を期待しているのに「なにぬねの」になってしまいますし(期待しているのは「んあ(んい)(んう)など」という文字)、次の文字がnを期待しているのに「nn」ではなく「n」を入力してしまうと、「んな」を期待しているのに「な」になってしまいます。
ついでですから、最後の「せんせいさん」も見てください。
「se n se i sa nn」ですね。
この最後の「nn」は「n」ではなく「nn」で終わる必要がありますね。
これが「一つの文字の入力可能形式は動的に変化する」の意味です。

問題は「ん」だけではありません。
続きを見ていきましょう。
「o ti ru syi ta kke」となりますね。
これをもう少し愚直に書くと、こうなります。
「o ti ru si li ta ltu ke」
当然どちらのパターンにも対応させなければなりません。
今回の場合ですと「っ」は「k」「ltu」「xtu」が可能であるとわかりますね。
しかしこの「k」は常に「k」であるとは限りません。
例えば「っじ」という言葉を考えてみてください。
「ltu ji」ですが、この場合の「っ」は「j」「z」「ltu」「xtu」の4パターンが考えられるはずです。
また、「ltu」が「j」として入力されたなら、次の文字である「じ」は「ji」のみを受け付け「zi」は受け付けてはなりません。
「jji」という入力は可能ですが、「jzi」という入力は認められないからです。
「z」の場合も同様です。

具体的な対応方法

さて以上のような問題をはらんでいるタイピングゲーム(ローマ字入力)ですが、具体的にはどのように実装するのがよいのでしょうか?
僕は入力可能な文字一覧を集めたテーブルを作成し、そのテーブルと仮名文字を一つ一つ結びつけ、それから実際の入力の判定として用いました。
「ん」や「っ」は入力の最中に動的にテーブルを変更させています。

これが最適な方法とはとても思えないので、具体的なコードはご勘弁くださいw
もっと良い方法があれば、ぜひ実装してGitHubに公開してください。
丸パクリします。

どのようなゲーム性をもたせるのか

最後になりましたが、タイピングゲームも「ゲーム」です。
どのようなゲーム性をもたせるのか? というのは非常に重要な問題です。
僕は色々なミニゲームを頭の中で思いついているのですが、それらを実装するために共通でぜがひでも欲しかった機能があります。
それは、「複数の入力画面に対して入力可能にすること」です。

といっても、別のウィンドウにあるゲームに対して入力するとかではありません。
「あいうえお」「かきくけこ」「さしすせそ」「たちつてと」という4つの文字列(以下ターゲット)をゲーム画面に同時に表示し、プレイヤーはそのどの文字列に対しても入力可能にする、というものです。

これを可能にするために以下のような機能を実装しました。

1.プレイヤーがどのターゲットに対しても入力していないことを確認
2.プレイヤーの入力に対し、各ターゲットの最初の文字に対する入力可能文字を走査する
3.入力可能なものがあれば、そのターゲットに移行
4.入力可能なものがなければ、ミスタイプを通知

簡単には以上のような感じですが、「現在のターゲット」を優先したり、不要な場合は走査しなかったりと、入力者が混乱しないようにするためのモロモロも実際は組み込んでいます。

ゲーム公開の予定日

ちゅーわけで今回の記事は「タイピングゲームの作り方」をそれなりに深く掘り下げました。
ゲームとしての面白さを追求するためにプレイヤーの強化システムを導入したり(純粋なタイプ速度の判定には関係なし)、ストーリーをきちんと持たせたり、タイパーが楽しめるミニゲームを実装したりしたいなあなんて妄想しています
まあ、あくまでも妄想段階ですが……。

ちゅーわけで僕が現在どのようなゲームを作ろうとしているのの画像はしばし待たれよ!
ほなそんな感じで、またね。

フォローする