酷暑
日中に小一時間出かけるだけで今日のターンは終了した気分になる夏バテ気味な皆さんこんにちは。先日は例のジブリ映画を観に出掛け、映画館までの往復計一時間で全ての体力を使い果たしました。映画自体は「全く説明のない"千と千尋"」みたいな感じで、各要所毎のシーンは面白く飽きずに観れたのですが、鑑賞後に全体を振り返ると特に印象に残る場面がない、というなんとも不思議な映画でした。あと、「このキャラクターの声、ちょっと浮いてるな」と思ったらそれが菅田将暉でビックリ。あんな作りこんだ声で演技させるなら普通に声優使えばいいのに。
ゲームパッド対応
自作のアドベンチャーゲーム「W.T.」は既にアーリーアクセス版をSteamでリリースしていますが、東京ゲームダンジョン3での出展前にリリースしておきたい&東京ゲームダンジョン3に出展する試遊版を制作する必要があった事もあり、現状ではゲームパッドでの操作には対応していません。
とはいえ、最近ではPCゲームでもゲームパッドで操作するのが主流となっているので、現在はその対応中なのですが、ネックとなっているのは、uGUIに対してゲームパッドでどう操作するか、という事。
Unityではメニュー画面、オプション画面等を作成するために必要なButtonやTextBoxなどのUI(uGUI)が提供されているのですが、WindowsフォームやJavaScriptなどのWeb画面とは違い、フォーカスという概念がないので、マウス操作以外のゲームパッドやキーボードでのキー操作に対応してフォーカスを移動させるにはEventSystemを使ってちょっと工夫が必要です。
EventSystem
UnityでのUI操作は、EventSystemというコンポーネントを必ず使用します。
このEventSystemではどのオブジェクト(UI)が現在アクティブなのか、どのオブジェクト(UI)が『選択中』なのかという事が管理されています。
例えば下の図のようなメニュー画面でマウス操作ではなくキーボード操作でボタンを選択したい場合を想定します。
この時、ゲーム開始直後に最初に選択されるボタンの設定はEventSystemの「First Selected」という項目で設定することができます。
この項目に起動時、選択状態にしておきたいゲームオブジェクト(ボタン)を指定しておくと
ゲーム起動時に選択状態となります。(上の動画では選択状態は青くなるようにHighlightedColorを設定しています)
キーボード操作によるボタンの選択
最初に選択したいボタンは上記の設定にて実現することができますが、そこからキーボード操作で「選択状態」のボタンを移動させたい場合、Standalone Input Moduleというコンポーネントを使用します。
このStandalone Input Moduleでは横方向の入力(Horizontal Axis)と縦方向の入力(Vertical Axis)および決定ボタン(Submit Button)等の動作と、InputManager(UnityメニューのEdit→Project Settingから設定)で定義されている入力方法との紐づけが行われています。
Input Managerのウィンドウ
このInputManagerに関してはUnityのマニュアルを参照してください。
この設定はデフォルトならキーボードの矢印キーとゲームパッドの左スティックが設定されているので、通常なら特に意識することなく矢印キーと左スティックで選択状態のボタンを移動させることができます。
また、一部のボタンを非表示化(非アクティブ化)しても問題なく移動させる事もできます。
…と、ここまでなら特に工夫も必要なくキー操作対応が行えそうですが、InputManagerに定義された入力以外の操作でボタンの選択を行い場合、例えばTabキーで「選択状態」のボタンを移動させたい場合はStandalone Input Moduleの設定だけでは対応することができません。
方向入力以外によるボタン選択
方向入力による操作は継続しつつ、その他のキーでもボタン選択の操作を行いたい場合には、自力でスクリプト組む必要があります。
具体的にはそのキー(例えばTabキー)のキー押下(GetKeyDown)をUpdateで検知した場合、
- 現在「選択状態」となっているオブジェクト(ボタン)をEventSystemから取得する
- 「選択状態」ボタンの親クラスSelectableから、次のボタン(右、もしくは下)のボタンを取得する
- 次ボタンをEventSystemに渡して「選択状態」にする
という手順を行います。
void Update() { // Tabキー押下 if (Input.GetKeyDown(KeyCode.Tab)) { // 選択中のオブジェクト取得 GameObject nowObj = EventSystem.current.currentSelectedGameObject; // Selectableがある場合 if(nowObj.TryGetComponent<Selectable>(out var sr)) { // Selectableを取得 Selectable mySelectable = sr; // 一つ下のオブジェクトを選択 EventSystem.current.SetSelectedGameObject(mySelectable.navigation.selectOnDown.gameObject); } } }
上のスクリプトを実行すると
Tabキーによってボタンを選択することができます。
ゲームパッド対応には道半ば
前述のようにUnityのuGUIではフォーカスという概念がないので、Standalone Input Moduleの設定だけは中途半端な動作になります。
特にマウス操作と併用された場合、「選択状態」となるオブジェクトはボタンだけとは限らないので、ボタンやスティックを操作しても何の反応もしない、という状態に陥る事が多いです。
例えば、ボタンが選択されている状態でボタン以外の箇所をマウスでクリックされた場合、もう一度マウスでボタンをクリックしない限りは「選択状態」に戻らないので非常に面倒な事になります。
ここら辺はWindowsフォームのようにLostFocusイベントが検知されれば良いのですが、現状では自力で何とかするしかないようです。