Input Systemでボタンが押された瞬間をチェックしようとしているけど上手くいかないみたいなの…
Input Systemでは少し気を付けないといけない点があるわ。この辺を解説していくね。
Input Systemでボタンが押された瞬間や離された瞬間を検知する方法には、主に次の2通りがあります。
- Input ActionのPress InteractionまたはButtonを用い、performedコールバックで検知する
- Updateイベント等から状態を毎フレームチェックする
特別な理由がない限り、1つ目のperformedコールバックで検知する方法が簡単かつ安全です。
2つ目の方法では、Input ManagerのGetButtonDownやGetButtonUpメソッドのような使い方でチェックができます。しかし、Input System側の設定次第では正常動作しなくなる事があり注意が必要です。
本記事では、2種類の方法でボタンが押された瞬間、離された瞬間を判定する方法を解説します。使用上における注意点についても触れます。
- Unity 2022.1.23f1
- Input System 1.4.4
目次 非表示
前提条件
事前にInput Systemパッケージがインストールされ、使用可能になっているものとします。ここまでの手順が分からない方は、以下記事を参考にセットアップを済ませてください。
また、本記事ではInput Actionを経由して入力を取得するものとします。Input Actionについて分からない方は、以下記事をご覧ください。
Press Interactionで判定する
Pressという名前のInteractionを使用すると、ボタンが押された瞬間、離された瞬間、またはその両方を検知できます。
参考:Interactions | Input System | 1.4.4
これらの瞬間の検知は、通常はInput Actionのコールバック経由で行います。
なお、押された瞬間のみを判定したい場合は、ActionにInteractionを一切登録せず、Action TypeをButtonに設定するだけでも可能です。
参考:Interactions | Input System | 1.4.4
コールバック経由で取得する際は、必ずperformedコールバックのみを拾うようにする必要があります。他にもstarted、canceledコールバックがありますが、それぞれInteractionの開始と終了の際に呼ばれるため、意図しないタイミングで呼ばれるなどの不具合の原因となります。
ボタンが押されたかどうかの判定には、入力値の大きさと閾値で判定するため、アナログスティックなどが倒された瞬間、戻された瞬間を検知することも可能です。
Press Interactionの適用
押された瞬間や離された瞬間を検知したいActionにPress Interactionを適用します。
本記事では、押された瞬間、離された瞬間、両方の瞬間を検知するためのActionを定義し、それぞれ設定するものとします。
Press Interactionの設定内容は以下の通りです。
- Trigger Behaviour – どの瞬間を検知するかを指定する。
- Press Point – 押された判定とする閾値。未設定の場合はデフォルト設定(Input System Packageの設定側)が適用される。
Trigger Behaviourでは、以下の3種類の設定値から選べます。
- Press Only – 押された瞬間を検知する。
- Release Only – 離された瞬間を検知する。
- Press And Release – 押された瞬間と離された瞬間の両方を検知する。
上記瞬間を検知した時、Input Action側からPerformedコールバックが発火されます。スクリプト側からは、この該当ActionのPerformedコールバックをチェックすれば良いです。
ここまでのPress Interactionの設定の流れは以下動画のようになります。
次に、前述のPress InteractionのPerformedコールバックをスクリプト側から検知できるようにしていきます。
Player Inputの準備
本記事では、Player InputからUnity Event経由でスクリプト側に通知するものとします。Player Inputの使い方がわからない方は、以下記事をご覧ください。
まず、対象となるInput Actionアセットが適用されたPlayer Inputを準備します。
本記事では、空のゲームオブジェクトにPlayer Inputコンポーネントを追加し、Actions項目にInput Actionアセットを適用するものとします。また、BehaviourにInvoke Unity Eventsを設定するものとします。
タイミングを検知するスクリプトの実装
以下、Player InputからUnity Event経由でコールバックを受け取る例です。
押された瞬間、離された瞬間、その両方をコールバックで受け取るためのメソッドを定義しています。
上記スクリプトをPressInteractionExample.csという名前で保存しておきます。
コールバックの登録
前述のスクリプトを適当なゲームオブジェクトにアタッチします。
そして、Player InputのEvents項目より上記スクリプトのメソッドを該当するActionに登録します。
これでスクリプト側がコールバックを受け取ってログ表示できるようになりました。
実行結果
ボタンが押された瞬間、離された瞬間それぞれでデバッグログ表示されます。
両方のタイミングを検知するActionも期待通りの挙動になっています。
Updateイベントでチェックする
Press Interactionを使わないもう1つの方法として、従来のInput Managerのように、Updateイベントなどでタイミングをチェックする方法があります。
Input Action経由のほか、低レベルAPI(Keyboardクラス、Mouseクラスなど)から直接状態を見る方法があります。
ただし、この方法には1つ落とし穴があり、取り扱いには注意する必要があります(後述)
Input Action経由で判定する
Input Action経由で判定したい場合、該当するInput Actionをスクリプトから取得し、Updateイベント内で次のメソッドを用いることで判定できます。
- 押された瞬間 – InputAction.WasPressedThisFrameメソッド
- 離された瞬間 – InputAction.WasReleasedThisFrameメソッド
サンプルスクリプト
以下、Updateメソッドから指定された名前のAction(ボタン)が押された瞬間、離された瞬間にデバッグログを出力するサンプルです。
上記をUpdateExample.csという名前で保存し、適当なゲームオブジェクトにアタッチし、インスペクターより各種設定を行うと機能するようになります。
実行結果
期待通りの動作になりました。
スクリプトの説明
まず、PlayerInputから該当するInput Actionを予め取得しておきます。
FindActionメソッドを使用すると、Actionの取得失敗時にnullが返されます。
参考:Class InputActionAsset| Input System | 1.4.4
そして、実際に押された判定はUpdateメソッド内の以下コードで行っています。
低レベルAPIから参照する
Input Actionを用いずに、KeyboardクラスやMouseクラスなどから直接ボタン入力を参照する際も、ほぼ同様の流れで実装できます。
本記事では、キーボードのAキーの押された瞬間、離された瞬間を判定する例を紹介します。
サンプルスクリプト
Keyboardクラスから直接Aキーの押された/離されたタイミングをチェックする例です。
上記をKeyboardExample.csという名前で保存し、適当なゲームオブジェクトにアタッチすると機能します。
実行結果は先の例と同じのため、割愛させていただきます。
スクリプトの説明
まず、該当するボタンのインスタンスを取得します。型はButtonControlクラスです。
参考:Class ButtonControl| Input System | 1.4.4
キーボードの押された瞬間、離された瞬間を判定する部分は以下コードです。
Input Action経由の時とは違い、次のプロパティで判定しています。
- 押された瞬間 – ButtonControl.wasPressedThisFrameプロパティ
- 離された瞬間 – ButtonControl.wasReleasedThisFrameプロパティ
使用上の注意点
この方法で押された瞬間/離された瞬間を判定する場合、Input Systemパッケージの設定に注意する必要があります。
影響する項目は、Project Settings > Input System PackageのUpdate Mode項目です。
スクリプトからチェックする際は、このUpdate Modeの更新タイミングに取得タイミングを合わせる必要があります。
Update Modeには次の3種類を設定可能です。
- Process Events In Dynamic Update – UpdateイベントのタイミングでInput Systemの状態を更新する。
- Process Events In Fixed Update – FixedUpdateイベントのタイミングでInput Systemの状態を更新する。
- Process Events Manually – スクリプト等からマニュアルでInput Systemの状態を更新する。
参考:Input settings | Input System | 1.4.4
例えば、Update ModeにProcess Events In Fixed Updateが設定されている場合、次のようにFixedUpdateイベント内で押されている/離されている判定を行わなければなりません。
Update Modeの設定とスクリプトの取得タイミングが合っていないと正しく判定できません。
例えば、Input Systemの更新タイミングがFixedUpdateイベントなのに対し、スクリプトからの取得タイミングがUpdateイベントである場合、正しく取得できません。
さいごに
ボタンの押された/離されたタイミングを検知する2種類の方法を解説しました。
通常はPress Interactionを判定する方法を推奨しますが、やむを得ずUpdate等でチェックしなければいけない状況でも可能です。
Updateイベント、FixedUpdateイベントでチェックする際は、Input SystemパッケージのUpdate Modeの設定に注意しながら実装すると良いでしょう。