Unityの新しいInput Systemを初めて使おうとしているんだけど、使い方が分からないの。
軽く動かしてみるところまで一緒にやっていくね。
Unity公式の新しい入力システムパッケージInput Systemの入門者向け記事です。
本記事では、Input Systemパッケージのインストール方法から、最低限使えるようにするところまでを解説していきます。
また、後半ではInput Systemで出来ることについても紹介します。
- Input Systemを初めて使う、または理解に不安がある方
- Unityの基本操作を理解している方
- 基本的なC#スクリプトが書ける方
- Input Systemでどのようなことが出来るかを知りたい方
- Unity 2022.1.16f1
- Input System 1.5.1
目次 非表示
Input Systemとは
従来の入力システムに代わる新しい入力システムです。
キーボードやマウスを初め、ゲームパッド、ジョイスティック、タッチディスプレイ、その他独自デバイスなど様々な種類のデバイスを統合して扱うことが可能です。
参考:Input System | Input System | 1.5.1
従来の入力(Input Manager)はビルトイン機能として手軽に使える反面、次のような機能を実現しようとすると、自前の管理クラスを実装したり、複雑なロジックを書くなど面倒な側面がありました。
- ゲームパッドのボタンや軸の割り当て
- 長押し、ダブルタップなどの判定
- キーコンフィグ
- タッチとゲームパッドなど異なる操作の共有(ただし、旧Input Managerでもある程度は可能)
Input Systemを用いると、このような問題を吸収してくれます。
他にも、旧Inputにはない便利機能が存在します。
Input Systemのインストール
新しいInput Systemは、Unityパッケージとして配布されています。Package Managerよりインストールします。
トップメニューのWindow > Package Managerを選択し、Package Managerウィンドウを開きます。
ウィンドウが開いたら、左上タブよりPackages: ~ボタンをクリックし、Unity Registryを選択します。
また、バージョンによっては以下のようにすぐ下にAllとServicesタブが並ぶことがあるため、Allのほうを選択します。
左のリストより、Input Systemを選択し、右下のInstallボタンをクリックします。
すると、Input Systemのインストールが開始されるので完了まで待機します。
インストールが完了すると、次のWarningウィンドウが表示されることがあります。これは、旧型式のInput Managerを無効化して新しいInput Systemを有効かするかどうかを尋ねる内容です。
ここからは、旧Input Managerを併用する場合としない場合で手順が異なります。該当する手順のどちらかを実施してください。
サードパーティー製のアセットでは、従来の入力システムを有効にしないと動かないものが存在します。この場合は2のInput Managerを併用する手順を実施してください。
1.Input Managerを併用しない場合
そのままYesボタンをクリックしてInput Systemを有効化して再起動します。
Unityが再起動したらInput Systemパッケージのインストールは完了です。
2.Input Managerを併用する場合
Noボタンをクリックしてウィンドウを閉じます。
UnityメニューのEdit > Project Settings…を選択し、Project Settingsウィンドウを開きます。
左のリストからPlayerを選択し、Other Settings > Configuration > Active Input Handling*項目をBothに設定します。
すると、確認メッセージが表示されるため、ApplyボタンをクリックしてUnityを再起動します。
Unityが再起動したらInput Systemパッケージのインストールは完了です。
Input System Package (New)は、従来の入力システムを無効化し、新しい入力システムを有効化する設定です。Bothは従来と新しい入力システム両方を有効化して使えるようにする設定です。この設定は、Active Input Handling*項目からいつでも変更可能です。
キーボード入力を取得する最小限のコード
まず、Input Systemを使用してキーボード入力を取得する最小限のサンプルスクリプトを紹介します。
キーボードのAキーが押されているかどうかを判定する例です。
上記スクリプトをKeyboardExample.csとしてUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチします。
実行結果
ゲームを実行すると、Aキーの押下状態がログ出力されます。
スクリプトの解説
Input System関連のAPIはUnityEngine.InputSystem名前空間に定義されています。
キーボード情報はKeyboard.currentプロパティから参照します。
参考:Class Keyboard| Input System | 1.5.1
ただし、キーボードが接続されていない場合は上記がnullになるため、以下でnullチェックを行っています。
キーボードのAキーの情報は次のコードで取得します。
次のコードでも取得可能です。
変数aKeyはKeyControl型のインスタンスで、ここからキー入力状態を取得できます。
参考:Class KeyControl| Input System | 1.5.1
その他のキーの取得も同じような流れで行えます。詳細は公式リファレンスをご確認ください。
参考:Class Keyboard| Input System | 1.5.1
キーが押された瞬間かどうかはwasPressedThisFrame、離された瞬間かどうかはwasReleasedThisFrame、単に押されているかどうかの状態はisPressedプロパティから取得できます。
これらのプロパティは、従来の入力システム(Inputクラス)の以下メソッドと対応しています。
従来の入力システム(Inputクラス) | 新しい入力システム(Input System) |
Input.GetKeyDown() | wasPressedThisFrame |
Input.GetKeyUp() | wasReleasedThisFrame |
Input.GetKey() | isPressed |
マウス入力を取得する最小限のコード
マウスのボタンとカーソル位置を取得してログ出力する例です。
上記スクリプトをMouseExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチすると動作するようになります。
実行結果
左ボタンがクリックされたら、カーソル座標と共にメッセージ出力されます。
スクリプトの解説
マウス情報は、Mouse.currentプロパティから参照します。
参考:Class Mouse| Input System | 1.5.1
マウス情報もキーボード同様、接続されていないとnullになるため、nullチェックを行います。
マウスカーソルの位置は、以下のReadValueメソッドからスクリーン座標として取得できます。戻り値はVector2型です。
参考:Class Pointer| Input System | 1.5.1
マウスのボタンクリックの取得方法は、キーボードと同じです。以下はマウスの左ボタンの入力状態を取得する処理です。
ほかのボタン入力も同様に取得できます。詳細を知りたい方は以下リファレンスをご覧ください。
参考:Class Mouse| Input System | 1.5.1
Actionで入力取得を抽象化する
ここまでキーボードやマウスなどの入力値をデバイス固有のコードで取得する例を解説しました。
しかし、この方法ではゲームロジック側のコードがデバイス構成に依存してしまい、柔軟性や拡張性が損なわれてしまうデメリットがあります。
このような入力は、Actionという概念を用いて抽象化することで解決可能です。Actionとは操作の単位で、例えばキャラクターの「移動」や「ジャンプ」などといった操作をActionとして扱うことができます。
これにより、ゲームロジック側はどのコントローラーからの入力なのかを意識しないコードを書けるようになります。また、新しいコントローラーへの対応が楽になるというメリットもあります。
コントローラーとActionとのマッピングは、Bindingとして表現されます。
上記のように、スペースキーとSouthキーがマッピングされる「ジャンプ」というActionは、2つのBindingで表現されます。
参考:Input System Concepts | Input System | 1.5.1
Action経由で入力を取得する
次に、Actionを経由して入力を受け取れるようにしてみます。
Actionは、スクリプトからはInputActionクラスのインスタンスとして扱われます。
参考:Class InputAction| Input System | 1.5.1
InputActionのインスタンス化には様々なやり方がありますが、次のように[SerializeField]で定義してインスペクタから編集できるようにすることができます。
インスタンス化には様々なやり方があるため、初学者が躓きやすい部分かもしれません。しかし、いずれの方法でも最終的にInputActionインスタンスを(ラッパークラスなどで内部的に)生成して使えるようにする部分は一緒です。
サンプルスクリプト
以下、インスペクターから設定されたActionの入力値を毎フレームログ出力する例です。
上記をInputActionExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチします。
すると、次のようにインスペクタからActionを編集できるようになります。
例では、スペースキーをBindingとして追加してみることにします。
まず、Action右の「+」アイコンをクリックし、Add Binding項目を選択します。
すると、Actionのプロパティ画面が表示されるので、Path右のドロップダウンをクリックします。
どのデバイスのキーを割り当てるかの選択UIが表示されるため、該当するキーを選択します。
Listenボタンから実際に入力されたキーで割り当てる方法、その下の一覧から手動で選択する方法どちらでも可能です。
ここでは、Listenボタンをクリックした後、スペースキーを押下して候補を選択することとします。
これで設定は完了です。
実行結果
コンソールログに受け取った入力値が出力されます。
float型(1軸)の入力値として受け取っているため、0か1の値が出力されています。
ゲームパッドのトリガーボタンやスティックなどアナログ入力を割り当てた場合は0~1の間の値が出力されることでしょう。
スクリプトの説明
まず、インスペクターからActionを編集できるようにフィールドを定義しています。
その後、インスペクターからActionを設定すると、実行時にInputActionインスタンスが生成されます。
ただし、このままでは入力値を受け取れず、以下処理でオブジェクトが有効化されたタイミングなどでInputAction自身を有効化する必要があります。
参考:Class InputAction| Input System | 1.5.1
また、[SerializeField]などで独自に管理しているInputActionオブジェクトは、有効化/無効化を自分で行ったほうが望ましいです。
例では、OnDisableタイミングで無効化しています。
参考:Class InputAction| Input System | 1.5.1
これにより、次のコードでActionから入力値を受け取れるようになります。
InputAction.ReadValue<T>メソッドによって入力値を受け取れますが、テンプレート引数はActionで指定した型と一致する必要があります。
例ではスペースキー(1軸入力)なので、float型としています。
参考:Class InputAction| Input System | 1.5.1
コールバック経由でActionの入力を受け取る
もう一つActionの重要な特徴として、特定の入力があったときにコールバックとして入力値を渡す手段を提供しています。
これにより、例えば次のタイミングでイベントを発火させることが可能です。
- ボタンが押された瞬間
- 連続的な入力値(スティックやマウス位置など)が変化したとき
- ボタンが一定時間押され続けた時
- ダブルクリックされたとき
旧Inputでは、ボタンが押された瞬間はInput.GetButtonDownメソッド、長押しやダブルクリックの検知はUpdateやコルーチンなどを用いてロジックを実装するといったことが必要でした。
これをコールバック経由で入力を受け取ることによって、ゲームロジック側にこのようなロジックを書かずとも共通の処理で判定が可能になります。
サンプルスクリプト
以下は、コールバック経由でActionの入力値を受け取る例です。
上記をActionCallbackExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチすると使えるようになります。
前述の例と同様にActionをインスペクターから設定した後、Action右の歯車アイコンをクリックします。
すると、Actionのプロパティ画面が表示されるので、Action Typeを次のように設定してください。
- Value – スティックなど値が入力したときにコールバックを受け取る設定
- Button – ボタンが押された瞬間のコールバックを受け取る設定
例では、Action TypeをButtonに設定して、ボタンが押された瞬間にコールバックを受け取ってログ出力させるようにしてみます。
実行結果
キーが押されるたびにログ出力されるようになりました。
スクリプトの説明
まず、コールバックを受け取るメソッドを定義します。
戻り値や引数は必ずこの形式にする必要があります。
入力値の受取りは、引数contextに対してReadValueメソッドを呼び出すことで行います。
参考:Struct InputAction.CallbackContext| Input System | 1.5.1
そして、以下処理でコールバックを登録しています。
Actionにはstarted、performed、canceledの3種類のコールバックがあり、このうち特定の入力パターンを検知したときに発火するのがperformedです。
例では、ボタンを押したときなどにログを出したいためperformedコールバックに登録しています。
コールバックのより詳細な仕組みや挙動を知りたい方は以下記事をご覧ください。
購読不要になったコールバックは、以下処理で解除しています。
複数のActionをアセットとして管理する
ここまで単一のActionをスクリプトで管理する方法を紹介しました。
実際のゲームでは多数の操作(Action)を扱うことになるでしょう。また、プレイヤー操作以外にも、UI操作など全く異なる種類の操作も管理することになるかもしれません。
このような複数のActionの設定情報は、Input Action Assetというアセットファイルとして保持することが可能です。
プレイヤーやUIなどの種類の異なるActionはMapという単位でグループ分けし、切り替えると便利なことがあります。
また、Input Action Assetでは、Control Schemeというコントローラの種類(キーボード、マウス、ゲームパッドなど)に応じたグルーピング情報も管理できます。
例えば、Control Schemeがキーボードなら、キーボード操作のBinding入力だけ通すといった挙動も実現できます。
Input Action Assetを用いてActionの入力を受け取る具体的な方法については、以下記事をご覧ください。
PlayerInputでActionを管理する
Input Systemには、Input Action AssetのActionをラップして管理するPlayerInputコンポーネントがあります。
Actionからの入力通知をコールバックとして仲介(ラップ)して扱いやすくするほか、Mapの切り替えや、Control Schemeの自動切換えなども行ってくれる高機能クラスです。
参考:Class PlayerInput| Input System | 1.5.1
PlayerInputの詳細な使い方は以下記事で解説しています。
Input Systemで出来ること
ここまでInput Systemの導入手順から基本的な使い方まで解説してきました。
ここからは、Input Systemを使ってどんなことができるのか、使うことによってどんなメリットがあるのかを紹介していきます。
InteractionとProcessor
ボタンの長押しやタップ、マルチタップなどの操作入力を取得したい場合、旧Inputでは判定ロジックを自前実装したりアセットを使うなどで対応する必要がありました。
Input Systemでは、Interactionとしてこのような入力パターンを検知し、コールバックとして通知する機能を備えています。
参考:Interactions | Input System | 1.5.1
例えば、前述の例の「ボタンが押された瞬間」にコールバックを通知する挙動は、Default InteractionというInteractionの一種によるものです。
これ以外にも、次のようなInteractionがプリセットとして用意されています。
- Press – ボタンの押した瞬間、離した瞬間、またはその両方を通知する
- Hold – 一定時間以上ボタンが押し込まれたら通知する
- Tap – 素早くボタンを押して離した瞬間に通知する
- Slow Tap – ゆっくりとボタンを押して離した瞬間に通知する
- Multi Tap – 指定回数タップした瞬間に通知する
このような「特定パターンの入力があったかどうかの判定」は、コールバック経由で入力を受け取ることにより、受け取り側はこのような処理を意識しなくてよくなります。
例えば、ボタンを押した瞬間から長押しされた瞬間に変更したい場合でも、長押しのInteraction(Hold Interaction)をActionに追加するだけでよくなります。
また、Processorにより値の反転やデッドゾーン設定、スケールを掛けるといった入力値の加工が可能です。
参考:Processors | Input System | 1.5.1
例えば、「カメラの視線操作」をマウスとゲームパッド右スティックに対応する場合、両者の入力値の大きさが異なる場合があります。この場合、マウス移動量を0.1倍するなどといった値の加工(Scale Processorを適用)をすることで解決できます。
これ以外にも、次のようなProcessorが用意されています。
- Clamp – 値を範囲内に丸める
- Invert – 値を反転する
- Normalize – 値を正規化する
- Scale – 指定された係数を掛ける
- Axis Deadzone – 1軸単位でデッドゾーンを設定する
- Stick Deadzone – 2軸スティック入力を円形でデッドゾーンを設定する
このようなInteractionやProcessorは、Actionのプロパティ画面から追加できます。
他にも、既存のInteractionやProcessorだけでは物足りない場合、これらを自作することも可能です。
複数キー操作の合成
プレイヤーをWASDキーや十字キーで移動させる際、4つのボタンに方向を割り当てて最終的に移動ベクトル(Vector2型の値など)を求めたいケースがあります。
これは、複数のBindingの入力を合成して一つの入力値にしたり、入力値の型を変換したりするComposite Bindingを用いると楽です。
参考:Input Bindings | Input System | 1.5.1
ActionにBindingを追加する際に選択できます。
以下、4方向入力のComposite Bindingを設定する例です。
受け取り側は次のコードで実現できます。
上記コードの受取り部分は次のようにVector2型で受け取って処理できるようになっています。
ほかにも、複数ボタンが同時に押されたときだけ入力を流すComposite Bindingも提供されています。
キーコンフィグの実装
Input Systemでは、ユーザーの要求に応じて動的にマッピングを変更(リバインド)する機能も提供されています。
参考:Class InputActionRebindingExtensions| Input System | 1.5.1
これによりキーコンフィグ機能を比較的楽に実装できます。
例えば、設定画面でキー割り当てのボタンが押されたら、ユーザーによるキー入力を待機し、押されたときにキーを割り当てるといった一連のインタラクティブなリバインドを実現する専用APIが用意されています。
また、これらのリバインド情報をJSONとして読み書きする専用メソッドも用意されています。
複数プレイヤーへの対応
PCやゲーム機にコントローラーを複数接続してプレイするローカルマルチにも対応しています。
これは、PlayerInputManagerコンポーネントとして提供されています。
参考:Class PlayerInputManager| Input System | 1.5.1
これにより、プレイヤー毎のコントローラー割り当てや入退室の管理などを楽に行ってくれます。
デバッグ機能
接続されたコントローラーの入力状態をモニタリングしたり、アプリケーション側で問題が起こっていないかを確認したりできるInput Debuggerがあります。
参考:Debugging | Input System | 1.5.1
トップメニューのWindow > Analysis > Input Debuggerから開けます。
Input Debugウィンドウでは、現在有効なActionや接続中デバイスなどの一覧を見ることができます。
コントローラーなどの入力データをモニタリングしたいときは、デバイスをダブルクリックすれば良いです。
バーチャルパッドの実装
スマートフォンなどのバーチャルパッド関連の機能も提供しています。
参考:On-screen Controls | Input System | 1.5.1
これを用いると、次のようにUI上のボタンやスティックを操作したときにBindingの入力として受け取れるようになります。
バーチャルパッドの使い方については、以下記事で解説しています。
バーチャルマウスの実装
ゲームパッドからOSのカーソルを動かしたり、UIの画像をカーソルと見立てて操作したりすることも可能です。
これはVirtual Mouseコンポーネントとして提供されています。
参考:Class VirtualMouseInput| Input System | 1.7.0
これを用いると、次のようにゲームパッドから好きなカーソルを操作してUI上のボタンを操作できるようになります。
詳細な使い方は以下記事をご覧ください。
コントローラーの振動
XboxコントローラーやDUALSHOCKシリーズなど振動をサポートしているゲームパッドを、次のようなコードで簡単に振動させることができます。
参考:Class Gamepad| Input System | 1.5.1
使い方の詳細は以下記事で解説しています。
Update以外での入力状態更新
旧Inputでは、基本的にUpdateイベント内で入力値を読む必要がありました。
Input Systemでは設定により、FixedUpdateイベントや任意タイミング(Manual)で入力状態を更新するように設定変更できます。
例えば、Rigidbodyを主体にキャラクターを操作するゲームなどは、FixedUpdateイベントで入力状態を更新すると都合の良い場合があります。
詳細は以下マニュアルをご確認ください。
参考:Input settings | Input System | 1.5.1
Starter Assetsでの活用例
別アセットになりますが、FPSやTPSのサンプルであるStarter Assetsのプレイヤー操作部分にもInput Systemが活用されています。
こちらはPlayerInputコンポーネント経由でActionの入力を受け取っているようです。
アセットは以下アセットストアのページより入手できます。
First Person Character Controller(一人称視点操作版)
Third Person Character Controller(三人称視点操作版)
Starter Assetsの導入方法は以下記事でも解説しています。
さいごに
新しいInput Systemのインストールから最低限使えるようにするところまでを解説しました。
また、Input Systemを使うことによってどのようなメリットが得られるか、どんなことができるかについても紹介しました。
字数の都合上割愛させていただいた機能などもあります。最新機能については公式リファレンスやChangelogをご確認ください。