

インスペクターからInput SystemのActionを指定する時、直接指定なのかInput Action Assetの参照なのかを場面に応じて変える方法はないの?



InputActionProperty構造体を使えば良いわ。
Input SystemのActionをスクリプトから扱う際、インスペクターからActionを指定する方法は主に次の2通りが考えられます。
- Input Actionの設定内容を直接指定する
- Input Action Asset側で管理しているAction(参照)を指定する
両者はそれぞれデータの持ち方が別ですが、InputActionProperty構造体を使うと、同じスクリプトで動的にどちらの方法でActionを設定するかを切り替えることができます。
参考:Struct InputActionProperty | Input System | 1.5.1
InputActionProperty型として[SerializeField]などでフィールド定義すると、以下のようにインスペクターから指定方法を切り替えてActionを設定できるようになります。
本記事では、このInputActionPropertyの使い方について解説していきます。
- Unity 2022.2.16f1
- Input System 1.5.1
前提条件
事前にInput Systemパッケージがインストールされ、有効化されているものとします。
ここまでの手順は以下記事で解説しています。
また、Input Action経由で入力を受け取ることとします。
Input Actionの基本的な使い方は以下記事で解説しています。
InputActionProperty構造体の使い方
次のようにフィールド定義するだけで使えます。
// InputActionProperty構造体のフィールドを定義
// これでインスペクターからの設定が可能になる
[SerializeField] private InputActionProperty _actionProperty;
以下、InputActionProperty構造体をフィールドで定義し、ここからInputAction経由で入力を取得するサンプルです。
using UnityEngine;
using UnityEngine.InputSystem;
public class InputActionPropertyExample : MonoBehaviour
{
// InputActionProperty構造体のフィールドを定義
// これでインスペクターからの設定が可能になる
[SerializeField] private InputActionProperty _actionProperty;
private void Awake()
{
// InputActionインスタンスを取得
var action = _actionProperty.action;
// Actionが無かったら何もしない
if (action == null) return;
// performedコールバックにOnPerformedメソッドを登録
action.performed += OnPerformed;
// Actionを有効化して入力を受け取れるようにする
action.Enable();
}
// インスペクターで設定されたActionのperformedイベントが発火したら呼ばれる
private void OnPerformed(InputAction.CallbackContext context)
{
// InputActionの名前をログ出力
Debug.Log($"OnPerformed: {context.action.name}");
}
}
上記をInputActionPropertyExample.csという名前で保存し、適当なゲームオブジェクトにアタッチします。
すると、以下のようにインスペクターからActionを設定できるようになるため、お好みのActionを設定してください。

上記のようにUse Reference項目のチェックを外すと、Actionを直接スクリプト側で定義できるようになります。
Use Referenceにチェックを入れると参照モードとなり、Input Action AssetのActionのアタッチ(参照の指定)が可能になります。

例では、直接Actionを定義し、スペースキーが押されたらperformedコールバックが発火するBindingを定義してみます。
実行結果
指定されたActionのキーが押されるたびに、コンソールにログ出力されます。
参照モードで実行すると、次のようにInput Action Assetで定義したAction名がログ出力されます。
スクリプトの説明
まず、[SerializeField]属性などでInputActionProperty型をシリアライズ可能なフィールドとして定義します。
// InputActionProperty構造体のフィールドを定義
// これでインスペクターからの設定が可能になる
[SerializeField] private InputActionProperty _actionProperty;
その後、上記のインスペクターから設定されたActionをInputActionインスタンスとして取得します。actionプロパティから取得できます。
// InputActionインスタンスを取得
var action = _actionProperty.action;
// Actionが無かったら何もしない
if (action == null) return;
未定義の場合もあり得るため、nullチェックも行っています。
InputActionインスタンスを無事に取得できたら、performedコールバックにメソッドを登録し、Actionを有効化します。
// performedコールバックにOnPerformedメソッドを登録
action.performed += OnPerformed;
// Actionを有効化して入力を受け取れるようにする
action.Enable();
Actionの有効化を忘れると、performedコールバックに登録しても入力を受け取れない(コールバックが発火しない)のでご注意ください。
InputActionProperty構造体の仕様
InputActionProperty構造体の仕様は以下リファレンスに記載されています。
参考:Struct InputActionProperty | Input System | 1.5.1
基本的に、スクリプト中から扱うのは次のactionプロパティでしょう。
public readonly InputAction action { get; }
直接指定か参照指定かによって返すActionを内部的に振り分けてくれるため、使用側が特に意識する必要はありません。
また、referenceプロパティによってActionへの参照(InputActionReference型)を取得することも可能です。
public readonly InputActionReference reference { get; }
ただし、参照モード(インスペクターからUse Referenceにチェックが入っている状態)でないと常にnullを返します。
InputActionProperty構造体の内部実装
内部的には次の3つのシリアライズ可能フィールドを持っています。 [1]
// 参照を使用するかどうか
[SerializeField] private bool m_UseReference;
// 直接指定時のInputAction設定情報
[SerializeField] private InputAction m_Action;
// 参照指定時のActionへの参照情報
[SerializeField] private InputActionReference m_Reference;
直接指定か参照指定かを示すフラグm_UseReferenceを持ち、それぞれの指定に応じた設定情報を両方保持しています。
直接指定の時はm_Actionフィールド、参照指定の時はm_Referenceフィールドが内部的に使用されます。
インスペクター上では、エディタ拡張(Property Drawer)によってm_UseReferenceフィールドの状態に応じて必要なフィールド(m_Actionかm_Referenceか)のみを設定可能になるように表示切り替えしています。
さいごに
InputActionPropertyをAction指定用のフィールドとして用いると、臨機応変にActionの指定方法を変えることができます。
スクリプトから単独のActionを指定する場合に活躍できるでしょう。
ただし、余分にフィールドを持つことになり、シリアライズされるデータサイズが増えることを念頭に置けば良いでしょう。