Input SystemからActionをスクリプトから扱う方法が色々あってよく分からないの…
それぞれ特徴があるので一通り解説していくね。最終的にはInputActionインスタンスを生成して使うことになるわ。
Input Systemの入力をAction経由で取得する手段は幾つか存在します。
最終的には直接または(ラッパークラス等で)間接的にInputActionクラスのインスタンスを生成し、ここから各種入力を受け取る流れになります。
主な方法は次の通りです。
- Input Action Assetのラッパークラスを生成して使う
- Player Inputコンポーネント経由で入力を受け取る
- InputActionをスクリプト内部で生成して使う
- InputActionをインスペクターから設定して使う
- InputActionReferenceクラスを使う
- InputActionProperty構造体を使う
このように、Input Actionからの入力方法は多岐に渡ります。
本記事では、上記のAction経由で入力を取得する方法および特徴について一通り解説していきます。
目次 非表示
前提条件
事前にInput Systemパッケージがインストールされ、有効化されているものとします。
ここまでの手順が分からない方は、以下記事を参考にセットアップを進めてください。
また、本記事で解説する内容は全てInput Action経由で入力を取得するものとします。
Input Actionの基本的な仕組みや使い方は以下記事で解説しています。
Input Action Assetのラッパークラスを生成して使う
Input Actionは通常、Input Action AssetでMapやActionを定義して使うことが多いでしょう。
Input Action Assetは拡張子が.inputactionsのアセットファイルで、開くと次のようなウィンドウで編集できるActionの定義情報です。
この中のActionへアクセスしたい場合、Input Action Assetのラッパークラスを自動生成してスクリプトから使うことができます。
この方法には次の特徴があります。
- Componentを使用しないピュアなC#クラスとして扱える
- 各種Actionにはプロパティとしてアクセスする
- 上記プロパティは内部的にキャッシュされているのでアクセスが高速
- Input Action Assetを更新する度にクラスが自動生成される
コードを自動生成する
前準備として、Input Action Assetを予め作成しておく必要があります。
作成方法が分からない方は、以下記事を参考に.inputactionsファイルを作成し、必要なMapやActionを定義してください。
例では、TestInputsという名前のInput Action Assetファイルを作成するものとします。
作成した後、Input Action Assetファイルを選択するとインスペクターよりコード生成するか否かを選択できます。
Generate C# Class項目にチェックを入れ、その下に現れる次の項目を設定した後、Applyボタンをクリックするとラッパークラスを定義したコードが自動生成されます。
- C# Class File – ファイルパス
- C# Class Name – ラッパークラス名
- C# Class Namespace – ラッパークラスの名前空間
ラッパークラスの生成を有効化すると、Input Action Assetが更新される度に再生成処理が走り、再コンパイル処理が走ります。
この時、Input Action Assetファイルを移動すると自動生成されるソースファイルが重複して作られてしまい、コンパイルエラーとなりますのでご注意ください。
また、後述するサンプルスクリプトで使用するラッパークラス名や名前空間は、それぞれC# Class Name、C# Class Namespace項目で設定した名前と一致させる必要があります。
サンプルスクリプト
ラッパークラスを生成したら、これをスクリプトからインスタンス化して入力を参照するスクリプトを実装します。
以下、「Player」というMap配下の「Fire」というActonの入力をチェックし、performedコールバックが発火したらログ出力する例です。
上記をGenerateCodeExample.csという名前で保存し、適当なゲームオブジェクトにアタッチすると機能するようになります。
もしラッパークラス名やMap名、Action名が異なる場合は適宜設定したものに修正してください。
実行結果
Fireという名前のActionのperformedコールバックが発火するとログ出力されるようになります。
スクリプトの説明
ラッパークラスは生成した後に破棄する必要があるため、フィールドなどに保持しておきます。
ラッパークラスはnewでインスタンス化します。
一度インスタンス化したラッパーは、最終的に必ずDisposeメソッドを呼んで破棄する必要があります。これは、ラッパークラスがIDisposableインタフェースを実装しているためです。
ラッパークラス内のActionへのアクセスは、[インスタンス].[Map名].[Action名]といった形でプロパティを見ればよいです。
上記の例では「Player」というMap名の下の「Fire」というAction名のActionのperformedコールバックを受け取る設定を行っています。
各種Actionへのプロパティを参照する際は、次のようなコードで内部的にActionへの参照がキャッシュされたものを用いています。
そのため、FindActionメソッドによる検索を回避するために取得側が変数などにキャッシュしておく必要はありません。
最終的にActionから入力を受け取るためには、Enableメソッドで有効化する必要があります。
無効化したい場合はDisableメソッドを使います。
そして、入力を受け取った際に次のコードでログ出力しています。
Player Input経由で入力を取得する
前述のInput Action Assetは、Player Inputコンポーネントを通じて取得することも可能です。
参考:Class PlayerInput| Input System | 1.5.1
特徴は次の通りです。
- Componentとしてゲームオブジェクトにアタッチし、設定して使用する
- InputActionを完全にラップし、各種スクリプトへの通知が可能
- これにより、スクリプト側からInputActionやPlayerInputクラスを直接参照しなくて良くなる
- 入力に応じてControl Scheme単位でActionを自動的に有効化・無効化できる
- 複数プレイヤーの管理(ローカルマルチ)に対応している
Player Inputの使い方の詳細は以下記事で解説しています。
設定の流れ
適当なゲームオブジェクトにPlayer Inputコンポーネントをアタッチし、Actions項目に該当のInput Action Assetを指定します。
次に、Player Inputから入力を受け取るスクリプトを実装します。
今回はFireというActionのみ実装し、performedコールバックを受け取ったらログ出力します。例ではUnityEventを通じてPlayer Inputから入力を受け取る場合を想定します。
上記をPlayerInputExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチします。
Player InputのBehaviour項目をInvoke Unity Eventsに設定し、Events配下の該当するActionにコールバックを指定します。
実行結果
一つ目の例と同様にFire Actionに該当するボタンが押されたらログ出力されるようになりました。
スクリプトの説明
実質的な処理は、以下のActionをコールバックで受け取る処理のみです。
Actionの有効化や破棄などの管理はすべてPlayer Input側で管理してくれます。
コールバックはstarted、prformed、canceledの3種類があるため、Performedのみ拾いたい場合はcontext.performedやcontext.phaseプロパティなどでフィルタリングする必要があります。
InputActionを直接スクリプトから生成して使う
ここまではInput Action Asset内部のActionに対して、ラッパークラスを生成したり、Player Inputコンポーネントを経由したりして入力を取得していました。
Input Action Assetを用いずとも単体のActionをスクリプトなどから生成して使うことも可能です。
コーディング量は多いですが、その分小回りが効く実装が可能です。
- GUIを使わずスクリプトベースで設定がすべて完結する
- 生成と破棄の管理を全てスクリプト側が責任を持って行う必要がある
- 柔軟性が高い
サンプルスクリプト
以下、実装例です。
上記をFromScriptExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチすると機能するようになります。
実行結果
キーボードのスペースキーを押すたびにログ出力されます。
スクリプトの説明
以下処理でInputActionインスタンスをパラメータ指定で生成しています。
Bindingに指定するControl PathやProcessor、Interactionなどは文字列で指定します。
参考:Class InputAction| Input System | 1.5.1
そして、以下コードでperformedコールバックを購読しています。
そして、スクリプト自身が有効化されるタイミングなどで忘れずにInputActionを有効化します。
InputActionの有効化を忘れると、入力を一切受け取れなくなりますのでご注意ください。
スクリプトが無効化された時は入力を受け取らないようにするため、以下処理でInputActionを無効化しています。
そして、スクリプトが破棄されるタイミングでInputActionインスタンスをDisposeで破棄します。
InputActionクラスはIDisposableインタフェースを実装しているため、必ずDisposeメソッドを呼び出して破棄するようにしてください。
InputActionを直接シリアライズして使う
InputActionクラスはシリアライズ可能なため、[SerializeField]属性を指定してインスペクターから編集させることが可能です。
- 柔軟性が高い
- Actionの設定はGUIベースで行える
サンプルスクリプト
以下、InputActionインスタンスをインスペクターから設定可能にしたスクリプトの例です。
上記をFromInspectorExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチするとインスペクターよりActionを編集できるようになります。
実行結果は1つ目の例と一緒のため割愛します。
スクリプトの説明
1つ目の例とは異なり、フィールドをシリアライズ可能にして定義しています。
これにより、インスペクターから専用UIでActionを設定できるようになります。
したがって、インスタンス生成処理をスクリプトから行う必要がなくなり、初期化処理はシンプルになります。
InputActionReferenceクラスを使う
ラッパーやPlayer Inputを使わずともInput Action Asset内のActionにアクセスする方法もあります。
このようなActionへの参照はInputActionReferenceクラスを用いると簡単に実現可能です。
参考:Class InputActionReference| Input System | 1.5.1
- Input Action Assetの設定情報を参照する
- 内部的にはInput Action Asset(ScriptableObject)をスクリプトから参照する
- 有効化・無効化の管理はスクリプト側が責任を持って行う
サンプルスクリプト
以下、InputActionReferenceクラスを通じてInput Action Asset内部のActionの入力を受け取ってログ出力する例です。
上記をInputActionReferenceExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチし、インスペクターよりActionを指定してください。
実行結果は前述の例と一緒のため割愛します。
スクリプトの説明
次のようにInputActionReferenceフィールドをシリアライズすると、インスペクターからInput Action Asset内のActionを指定できるようになります。
インスペクターから指定された(シリアライズされた)Actionは、InputActionReference.actionプロパティから取得できます。
これ以降のActionの有効化やコールバック登録の流れは、前述の例と一緒です。
InputActionReference.assetプロパティからInputActionAssetインスタンスそのものにアクセスすることも可能です。
InputActionProperty構造体を使う
InputActionクラスによるAction情報の直接指定、およびInputActionReferenceクラスによるInput Action AssetのActionへの参照を場面に応じて切り替えたい場合、InputActionProperty構造体を使うと簡単です。
参考:Struct InputActionProperty| Input System | 1.5.1
詳細の使い方は以下記事で解説しています。
- 柔軟性が高い
- 内部的にInputActionとInputActionReferenceのどちらを使うか切り替えられる
- それ以外はそれぞれ切り替えた側のクラスの使い方と一緒
サンプルスクリプト
以下、InputActionProperty構造体経由でActionを使う例です。
上記をInputActionPropertyExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチします。
すると、次のような設定項目がインスペクター上に表示されます。
Use Referenceのチェックを外すとActionを直接設定(InputAction相当)、チェックを入れるとInput Action AssetのActionを指定(InputActionReference相当)が可能になります。
実行結果は先ほどと一緒のため割愛します。
スクリプトの説明
フィールドを定義するところ以外は、InputActionReferenceの使い方と一緒です。
InputActionインスタンスの取得も同様です。
さいごに
Input SystemのActionの入力をスクリプトから取得する代表的な方法を一通り記しました。
Input Action Assetのラッパークラスを生成したり、Player Inputを使用する方法が代表的でしょう。
これ以外にも、InputActionを直接使用したり、InputActionReferenceでActionを参照したり、この両方を選択可能なInputActionPropertyを使用するといった方法もあります。
特にPlayer Input経由で取得する方法は複数コントローラーを扱うローカルマルチの実装が楽になるメリットがあるので、場面によって使い分けるのも良いでしょう。