ゲームパッドのスティックを十字キーとして使う方法を探してるの。これでメニューのカーソルを移動させたいの。
Input SystemにはこのようなControl Pathが存在するわ。標準機能だけで対応可能なの。
Input Systemのスティック入力を十字キー(D-pad)のように扱う方法の紹介です。
このような入力は、予め次のような上下左右の入力を表すControl Path として提供されています。
- <Gamepad>/leftStick/up – ゲームパッドの左スティック上入力
- <Joystick>/stick/right – ジョイスティックの右入力
参考:Gamepad Support | Input System | 1.3.0
これらのControl Pathは十字キーなどのD-padの入力のような振る舞いをします。
また、Event Systemのナビゲーションにも対応可能なため、スティックで選択項目を移動させたりすることも可能です。
Event SystemやPlayer Inputが自動生成するInput Actionの設定ファイルでは既にこのような設定がなされていますが、一部注意しないといけない点があります。
本記事では、スティック入力を十字キーのように扱う方法を解説するとともに、Event Systemとの連携方法とその注意点についても触れていきます。
- Unity 2022.1.4f1
- Input System 1.3.0
目次 非表示
前提条件
Input Systemがインストールされ、有効化されているものとします。ここまでの手順が分からない方は、以下記事をご覧ください。
また、本記事ではPlayer Inputを通じて入力を受け取るものとします。Player Inputの使い方が分からない方は以下記事をご覧ください。
実装の流れ
ゲームパッドの左右スティックとジョイスティックの4方向入力は、Control Path名の末尾に/up、/down、/left、/rightという文字列が追加されたControl Pathとして提供されています。
詳細は以下リファレンスのページにまとめられています。
参考:Gamepad Support | Input System | 1.3.0
参考:Joystick support | Input System | 1.3.0
4方向入力を受け取るActionとして定義できれば、参照元からはあたかもD-pad入力がなされているかのような振る舞いが実現できます。
本記事では、ゲームパッドの左スティックが倒された瞬間に押された通知(performedコールバックを発火)させることを例に解説します。
- 2軸入力のActionを定義
- 2D Vector Composite Bindingを上記Actionに定義
- 上記Composite BindingにleftStickの4方向入力を定義
- 上記ActionにPress Interactionを適用
ここまでの手順を踏んでActionの実装ができれば、あとはPlayer Input等を通じて4方向入力を受け取る処理を実装すれば良いです。
2軸のAction定義
Input Actionのアセット側に方向入力のActionを定義していきます。
例ではUIマップの下にNavigateというActionを定義するものとします。
そして、Action TypeにValue、Control TypeにVector 2を指定します。
もしAction TypeにPass Throughが指定されている場合、キーボードとゲームパッド等、複数コントローラーを併用するとEvent Systemとの連携などで誤動作する可能性があるので、基本的にValueを指定しておくのが安全です。
2D Vector Compositeの定義
前述のActionにComposite Bindingを追加します。Actionの右の+アイコンからAdd Up\Down\Left\Right Compositeを選択してください。
Modeなどの設定は初期値のままで問題ありません。
4方向のControl Pathの追加
そして、追加したComposite Binding配下の各方向に以下のようにControl Pathを設定します。
Binding | 追加するControl Path |
Up | leftStick/Up |
Down | leftStick/Down |
Left | leftStick/Left |
Right | leftStick/Right |
Press Interactionの適用
このままでもD-padのように最低限機能はしますが、スティック入力の値が変化するたびにperformedイベントが発火してしまいます。
キーボード入力は基本的に押された瞬間しかperformedコールバックが発火しませんが、スティック入力の場合は値が変化するたびに連続でperformedコールバックが発火することがあるといった違いがあります。
キーボード側と足並みを揃えてスティックが倒された瞬間のみperformedコールバックを発火させたい場合は、PressというInteractionを適用すれば良いです。
該当するActionを選択し、Interactionsの右側の+アイコンからPressを選択すると適用できます。
初期設定では押された瞬間のみperformedを発火するようになっているので、このままで問題ありません。
ここまでの手順を実施したら、Save AssetボタンをクリックしてInput Actionアセットの内容を保存しておきます。
入力受取の確認(必要ならば)
スティック入力があった時にデバッグログを出力するサンプルスクリプトです。本手順は確認用のため必須ではありません。
上記スクリプトをInputNavigationTest.csという名前で保存し、適当なオブジェクトにアタッチします。
そして、Player Inputを配置し、動画のようにNavigateアクションにコールバックの登録を行ってください。
実行結果
スティックが倒された瞬間に入力値がログ出力されるようになりました。
わかりやすさのため、実行画面ではスティックの入力状態を可視化させています。
- Windows10 Pro
- DUALSHOCK 4(PS4コントローラ)
なお、動画のスティック画像には以下アセットを使用させていただきました。
Player Inputが自動生成するデフォルトのInput Action
Player Input側にInput Action Assetが設定されていない状態で以下のCreate Actions…ボタンをクリックすると、デフォルトのInput Action Assetファイルが生成されます。
アセットを開くと、次のようにUI/NavigateというActionに4方向入力の設定が予めされています。
ゲームパッドの左右スティックの4方向入力のほか、ジョイスティックやキーボードの設定までされています。
ただし、前述の実装手順でも触れたようにAction TypeがPass Throughになっていたり、スティックとそれ以外(WASDやD-padなど)の入力でperformedコールバックが発火するタイミングが異なるため、必要なら設定を修正しておくと良いでしょう。
UI/NavigateのAction TypeをValueに、必要ならInteractionsにPressを適用しておけば良いです。
Event Systemと連携する場合
Event SystemとInput Systemを連携するときは、StandardInputModuleからInputSystemUIInputModuleにコンポーネントを置き換えて使います。
参考:UI support | Input System | 1.3.0
InputSystemUIInputModuleは初期設定ではDefaultInputActionsがInput Actionアセットとして適用されています。
これはPlayer Inputが自動生成するInput Actionアセットと一緒です。
そのため、もしEvent Systemとのナビゲーションを使いたい場合はDefaultInputActionsを複製したり、Player Inputからアセットを生成し、UI/NavigateのAction TypeをValueにしておくと良いです。
Interactionsは逆に何も設定しないでおきます。こうすることで、値が変化したときにEvent System側にコールバックを通知され、スティックの方向転換などに対応できます。
特に初期設定のままでは、UI/NavigateのAction TypeがPass Throughになっており、キーボードやD-pad入力でボタンの反応が悪くなったような症状になることがあるようです。これは、performedコールバックが発火した時に入力値0が得られてしまう瞬間があるためです。
実行結果
Navigateの設定を修正すれば、キーボードでもスティックでも同様の操作感で選択項目を移動できるようになります。
さいごに
スティックをD-pad入力のように扱う方法は、特定のControl Pathを参照するだけで可能です。
本記事ではComposite Bindingを用いて2軸入力として受け取る方法を紹介しましたが、単独のボタンを受け取るようなActionを定義することも可能です。
ただし、スティック入力の場合、値が変化したときに連続的にperformedコールバックが呼ばれることがあるため、そこに注意して活用すると良いかもしれません。