想定読者
- Web向けにかな入力にも対応したタイピングゲームをUnityを用いて開発している方
- ローマ字入力のタイピングゲームを開発できる方
当記事ではタイピングゲームの基本的な作り方については紹介しません。
はじめに
この記事の実装手法には、WebページのJavaScriptを編集し、unityInstance.SendMessage()
を用います。
そのため、unityroom など、WebページのJavaScriptを編集できない公開プラットフォームなどでは、実装が困難になるかもしれません。
ちょっとした技術解説
Unityでタイピングゲームを作る際にはMonoBehaviourのイベント関数であるOnGUI()
と、Event
クラスを用いてキーの押下処理を実行する手法がよく用いられます。
using UnityEngine;
public class Something : MonoBehaviour
private void OnGUI()
{
if(Event.current.type == EventType.KeyDown)
{
Process(Event.current.keyCode);
}
}
}
しかし、この手法ではUnity Editor上とブラウザ上で実行した場合において返されるKeyCodeが異なり、キーの位置が英字配列に対応したKeyCodeが返されてしまいます。
以下のテーブルは、筆者の手元環境であるmacOSとChromeにて行った際の実例です。
入力キー | 入力キー(かな) | 出力(Unity Editor) | 出力(Chrome、macOS) |
---|---|---|---|
@ | ゛ | KeyCode.At | KeyCode.LeftBracket |
{ | ゜ | KeyCode.LeftBracket | KeyCode.RightBracket |
_ | ろ | KeyCode.Underscore | KeyCode.None |
そのため、この手法では英字配列にはない「ろ」を安定して取得するのが困難です。
また、InputSystem.KeyBoard
のイベントonTextInput
からcharacter
を取得する手法があります。
using UnityEngine;
using UnityEngine.InputSystem;
public class Something : MonoBehaviour
{
private void Awake()
{
if (Keyboard.current is { } keyboard)
{
keyboard.onTextInput += character => {
Process(character);
};
}
}
}
しかし、この手法では「Shift+0」にあたる「を」を安定して取得できません。
ローマ字入力では、この技術仕様を意識する必要はございません。しかし、かな入力に対応させるには何かしらの解決手法を用いる必要があります。そして次節にて解決手法の一例を紹介します。
解決手法
JavaScriptのキー押下イベントkeydown
から取得できるstring値e.code
をunityInstance.SendMessage()
を用いてUnity+WebGL側で処理させます。
e.code
は最新のブラウザなら共通であり、安定して「ろ」や「を」を取得することができます。
実装方法
Unity側
まず、OnGUIの部分はWebGLビルドでは無効になるようにプリプロセッサを入力します。
+ #if UNITY_EDITOR
private void OnGUI()
{
if(Event.current.type == EventType.KeyDown)
{
Process(Event.current.keyCode);
}
}
+ #endif
そしてKeyCodeDetector.cs
というMonoBehaviour継承クラスを生成します。
using System.Collections.Generic;
using UnityEngine;
public class KeyCodeDetector : MonoBehaviour
{
private readonly Dictionary<string, KeyCode> _externalKeyCodes = new() {
{ "Digit0", KeyCode.Alpha0 },
{ "Digit1", KeyCode.Alpha1 },
{ "Digit2", KeyCode.Alpha2 },
{ "Digit3", KeyCode.Alpha3 },
{ "Digit4", KeyCode.Alpha4 },
{ "Digit5", KeyCode.Alpha5 },
{ "Digit6", KeyCode.Alpha6 },
{ "Digit7", KeyCode.Alpha7 },
{ "Digit8", KeyCode.Alpha8 },
{ "Digit9", KeyCode.Alpha9 },
{ "KeyA", KeyCode.A },
{ "KeyB", KeyCode.B },
{ "KeyC", KeyCode.C },
{ "KeyD", KeyCode.D },
{ "KeyE", KeyCode.E },
{ "KeyF", KeyCode.F },
{ "KeyG", KeyCode.G },
{ "KeyH", KeyCode.H },
{ "KeyI", KeyCode.I },
{ "KeyJ", KeyCode.J },
{ "KeyK", KeyCode.K },
{ "KeyL", KeyCode.L },
{ "KeyM", KeyCode.M },
{ "KeyN", KeyCode.N },
{ "KeyO", KeyCode.O },
{ "KeyP", KeyCode.P },
{ "KeyQ", KeyCode.Q },
{ "KeyR", KeyCode.R },
{ "KeyS", KeyCode.S },
{ "KeyT", KeyCode.T },
{ "KeyU", KeyCode.U },
{ "KeyV", KeyCode.V },
{ "KeyW", KeyCode.W },
{ "KeyX", KeyCode.X },
{ "KeyY", KeyCode.Y },
{ "KeyZ", KeyCode.Z },
{ "Minus", KeyCode.Minus },
{ "Equal", KeyCode.Caret },
{ "IntlYen", KeyCode.Backslash },
{ "BracketLeft", KeyCode.At },
{ "BracketRight", KeyCode.LeftBracket },
{ "Semicolon", KeyCode.Semicolon },
{ "Quote", KeyCode.Colon },
{ "Backslash", KeyCode.RightBracket },
{ "Comma", KeyCode.Comma },
{ "Period", KeyCode.Period },
{ "Slash", KeyCode.Slash },
{ "IntlRo", KeyCode.Underscore }
};
public void ExternalInput(string input)
{
if(_externalKeyCodes.TryGetValue(input, out var keyCode))
{
Process(keyCode);
}
}
}
このファイルを作り終えたら、GameObjectにアタッチしをScene上に置きます。
Shift押下処理につきましては省略します。
Web側
Unity+WebGLを実行するためのJavaScriptから以下の文を探し、window.addEventLister("keydown")
を追加します。
// ----------省略----------
const script = document.createElement("script");
script.src = loaderUrl;
script.onload = () => {
createUnityInstance(canvas, config, () => {
}).then((unityInstance) => {
document.querySelector("#unity-fullscreen-button").onclick = () => {
unityInstance.SelFullscreen(1);
}
+ window.addEventListener("keydown", (e) => {
+ unityInstance.SendMessage("KeyCodeDetector", "ExternalInput", e.code);
+ });
}).catch((message) => {
alert(message);
});
// ----------省略----------
これにて、かな入力にも対応したUnity+WebGLタイピングゲームを作ることができます。
さいごに
記事内のソースコードは自由に利用、改変しても大丈夫です。