【Unity】Input Systemでゲームパッド対応

当サイトで紹介する商品・サービス等の外部リンクは、アフィリエイト広告を含む場合があります。
スポンサーリンク
本記事を読むと以下の実行ができます

Input SystemのInputActionReferenceを使って、ゲームパッドでキャラクターの移動とジャンプを操作できるようになります。

Unityでプレイヤー操作実装する際に、キーボード操作だけでなく「ゲームパッド(コントローラー)にも対応したい」という場面が出てきます。

特にアクションゲームやプラットフォーマーでは、スティックでの移動とボタンでのジャンプはほぼ必須の操作です。

本記事では、Unityの新しいInput SystemとInputActionReferenceを使い、移動・ジャンプという最小構成でゲームパッド対応を実装する方法を分かりやすく解説します。

Gamepad.currentを直接参照する方法やPlayerInputコンポーネントに依存する方法とは違う、疎結合で使い回しやすい設計です。

マウス操作の導入を紹介しています。
本記事は次の人におすすめ
  • Unityでゲームパッド(コントローラー)対応を実装したい人
  • 新しいUnity Input Systemの基本的な使い方を知りたい人
  • InputActionReferenceを使った疎結合な入力処理の設計を学びたい人
  • Gamepad.currentを直接参照するコードから卒業したい人
  • ジャンプ入力の判定でバグが起きて困っている人
スポンサーリンク

Input System

Input Systemは、キーボード・マウス・ゲームパッドなどの入力をまとめて扱える、Unityの新しい入力の仕組みです。

XboxコントローラーやPlayStationコントローラー(DualSense)などのゲームパッドに対応したいときや、同じ操作をキーボードとゲームパッドの両方で行えるようにしたいときに使います。

従来のInput.GetAxis()などを使う古い入力システム(Input Manager)でもある程度のゲームパッド対応は可能でしたが、デバイスごとの差異を吸収しづらく、コードが複雑になりがちでした。

Input Systemでは、実際の入力デバイスと、ゲーム内の意味(「移動する」「ジャンプする」)をInput Actionという単位で分けられます。そのため、デバイスが変わってもコード側を変更せずに済みます。

Input Systemを使うには、パッケージの導入と、入力を定義するInput Actionsアセットの作成が必要です。

参考:Input System – Unity マニュアル

Input Systemパッケージの導入

Unity Input Systemは標準では有効になっていないため、Package Managerからインストールする必要があります。

  1. メニューから Window > Package Manager を開きます
  2. 検索欄で「Input System」を検索し、Install をクリックします
  3. インストール後、「新しい入力システムに切り替えますか?」という確認ダイアログが表示されるので Yes を選択します(Unityの再起動が必要です)

Yesを選ぶと、Edit > Project Settings > Player > Active Input Handling が Input System Package (New) に切り替わります。従来のInput Managerを使うコードが他にある場合は、動作しなくなる点に注意してください。両方を併用したい場合は Both を選択します。

Input Actionsアセットとゲームパッドのバインディング設定

次に、実際の入力を定義するInput Actionsアセットを作成します。

  1. Projectウィンドウで右クリックし、Create > Input Actions を選択してアセットを作成します
  2. 作成したアセットをダブルクリックしてエディタを開きます
  3. Action Mapsに「Player」などの名前でマップを作成します

各アクションの+ボタンからバインディングを追加し、Listen機能を使って実際にゲームパッドを操作するとバインディング候補が自動検出されるので、それを選択すると設定が楽になります。

設定が終わったら忘れずにSave Assetをクリックしてください。

InputActionReference

InputActionReferenceは、Input Actionsアセットの中にある特定のInput Actionを、Inspectorから参照するための型です。スクリプトにアクション名を文字列で書かずに、「どのアクションを使うか」をInspectorで選べます。

方法特徴
Gamepad.currentを直接参照コード量は少ないが、デバイスの差し替えや複数デバイス対応がしづらい
PlayerInputコンポーネントイベント駆動で扱いやすいが、コンポーネントへの依存度が高くなる
InputActionReferenceInspector上でアクションを差し替え可能。専用の入力ハンドラークラスに集約でき、疎結合な設計にしやすい

InputActionReferenceは、同じ入力ハンドラークラスを別のキャラクターやプレハブで使い回したり、テスト用に別のInput Actionsアセットへ差し替えたりしやすくなります。

参考:InputActionReference – Input System ドキュメント

InputActionReferenceで実装する移動・ジャンプ入力

本記事では、InputActionReferenceを使って、ゲームパッドの移動(左スティック)とジャンプ(ボタン)を取得する入力ハンドラーを実装します。

入力の取得だけを専用クラス(PlayerInputHandler)に切り出し、実際の移動処理・ジャンプ処理からはMoveInput・JumpWasPressedThisFrameという2つのプロパティを参照するだけで済むようにすることで、キーボードやマウスなど他の入力方式にも差し替えやすい設計を目指します。

実装にはこちらのゲームパッドを使用しました。手ごろで普段のゲームでも使うことができます。

ソースコード

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerInputHandler : MonoBehaviour
{
    [SerializeField] private InputActionReference moveAction;
    [SerializeField] private InputActionReference jumpAction;

    public Vector2 MoveInput { get; private set; }
    public bool JumpWasPressedThisFrame { get; private set; }

    private void OnEnable()
    {
        moveAction.action.Enable();
        jumpAction.action.Enable();
    }

    private void OnDisable()
    {
        moveAction.action.Disable();
        jumpAction.action.Disable();
    }

    private void Update()
    {
        MoveInput = moveAction.action.ReadValue<Vector2>();
        JumpWasPressedThisFrame = jumpAction.action.WasPressedThisFrame();
    }
}

解説

  • 名前空間
UnityEngineMonoBehaviour・Vector2など、Unityの基本機能を使うため
UnityEngine.InputSystemInputActionReferenceなど、Input Systemの機能を使うため(パッケージの導入が必要)
  • フィールド・プロパティ
moveAction移動に使うMoveアクションの参照。Inspectorで設定する
jumpActionジャンプに使うJumpアクションの参照。Inspectorで設定する
MoveInputスティックの傾き(-1〜1のVector2)。ほかのスクリプトから読み取る
JumpWasPressedThisFrameこのフレームでジャンプボタンが押されたか。ほかのスクリプトから読み取る

MoveInput・JumpWasPressedThisFrameは{ get; private set; }としているため、ほかのスクリプトからは読み取りだけができ、書き換えはできません。

InputActionReferenceでアクションを参照

InputActionReferenceは、Input Actionsアセット内の特定のInput ActionをInspector上から参照できる型です。

[SerializeField] private InputActionReference moveAction;
[SerializeField] private InputActionReference jumpAction;

コード内に直接アクション名を文字列で書く必要がなく、Inspectorから見た目でどのアクションを使っているか確認できます。

Gamepad.currentを直接参照する実装と違って、キーボード用のInput ActionsアセットとゲームパッドMap用のアセットを差し替えるだけで入力元を切り替えられます。

同じPlayerInputHandlerを別のプレハブで使い回す際にも、参照先のアクションを変えるだけで対応できる点が疎結合設計のメリットです。

移動入力をVector2で取得する

MoveInput = moveAction.action.ReadValue<Vector2>();

MoveアクションはAction TypeをValue(Vector2)に設定しているため、ReadValue()でスティックの傾き具合をVector2として取得できます。x軸が左右、y軸が上下の入力値(-1〜1の範囲)です。

取得したMoveInputは、別のスクリプト(プレイヤーの移動処理を担うクラスなど)からplayerInputHandler.MoveInputとして参照し、transform.TranslateやRigidbody.linearVelocityなどに渡してキャラクターを動かすといった使い方をします。

Rigidbodyで移動させる処理はこちらで解説しています。

ジャンプ入力を1フレームだけ検知する(WasPressedThisFrame)

JumpWasPressedThisFrame = jumpAction.action.WasPressedThisFrame();

WasPressedThisFrame()は、そのボタンが「このフレームで押された瞬間」かどうかを返すメソッドです。

ジャンプのように「押した瞬間に1回だけ処理を実行したい」動作には、このWasPressedThisFrame()を使うのが適切です。

キャラクターのジャンプ処理はこちらで解説しています。

isPressedにしない理由

InputActionにはisPressed(現在押されているかどうか)とWasPressedThisFrame()(このフレームで押された瞬間かどうか)という似た名前のプロパティ・メソッドがあります。

ジャンプ処理をisPressedで判定してしまうと、ボタンを押し続けている間、毎フレーム「押されている」と判定され続けてしまいます。その結果、Update()が呼ばれるたびにジャンプ処理が実行され、意図せず連続ジャンプしてしまうバグにつながります。

// 悪い例:ボタンを押している間ずっとtrueになる
if (jumpAction.action.IsPressed())
{
    Jump(); // 毎フレーム呼ばれてしまう
}

// 良い例:押した瞬間の1フレームだけtrueになる
if (jumpAction.action.WasPressedThisFrame())
{
    Jump(); // 1回だけ呼ばれる
}

ジャンプやポーズメニューの開閉など、「1回の入力につき1回だけ処理したい」動作では、必ずWasPressedThisFrame()を使うようにしましょう。

逆に、ダッシュのように「押している間だけ継続する」動作にはisPressedが向いています。用途によって使い分けることが重要です。

実演

空のGameObject、またはプレイヤーオブジェクトにアタッチします。

設定が完了すると、他のスクリプトからplayerInputHandler.MoveInput・playerInputHandler.JumpWasPressedThisFrameを参照するだけで、ゲームパッドからの入力を取得できるようになります。

まとめ

本記事では、Unity Input SystemのInputActionReferenceを使い、ゲームパッドでの移動とジャンプを実装する方法を解説しました。

  • InputActionReferenceをInspectorで参照することで、入力元を差し替えやすい疎結合な設計にできる
  • 移動はReadValue()、ジャンプはWasPressedThisFrame()で取得する
  • ジャンプなど「1回だけ処理したい」入力はisPressedではなくWasPressedThisFrame()を使う

今回紹介したPlayerInputHandlerは移動とジャンプの最小構成ですが、同じ考え方でダッシュ・攻撃・ポーズメニューの開閉など他のアクションにも応用できます。

まずはこの最小構成で「ゲームパッドで動くもの」を作り、そこから少しずつアクションを増やしていくと理解が深まるのでおすすめです。

タイトルとURLをコピーしました