【Unity】InputSystemの基本的な使い方を知って入力操作を管理しよう!

InputSystemとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「InputSystemってなに?」

「InputSystemを使ったことが無くて入力方法が分からない。」

というお悩みの方に向けた内容となっています。

Unityでは、キーボードやマウスなどのデバイスから入力操作を行う際、これまでは「InputManager」というシステムが使われていました。

しかし、直近のUnity6.3のバージョンで作成したプロジェクトでは、デフォルトで「InputSystem」という機能が使われています。

このInputSystemというのは、様々な入力デバイスからの操作を統合的に管理している新しいシステムで、InputActionsを使うことで、移動やジャンプなどアクション単位で入力操作を管理して、スクリプトから処理を作ることができます。

そこで、このページでは、Unityで様々なデバイスからの入力を管理するInputSystemについて、仕組みや基本的な使い方までをまとめていきます。

開発環境
  • Windows11
  • Unity 6.3 LTS(6000.3.2f1)
この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

InputSystemとは?様々なデバイスからの入力を統合的に管理する仕組み

まずは、InputSystemがどういうものなのか、仕組みについて簡単にまとめておきます。

InputSystemとは、冒頭でも解説した通り、ゲームを操作するための様々なデバイス(キーボード、マウス、コントローラーなど)から入力された情報を統合的に管理しているシステムのことです。

もう少し簡単に言えば、ゲームを操作するデバイスの入力は、すべてこのInputSystemを介して入力されていて、その情報をスクリプトで受け取り、操作に合わせて処理が行われるように指令を送ることで、ゲームを動かすことができます。

このInputSystemの特徴として、InputActionsというアセットファイルを使って、アクション毎に入力操作を管理することができます。

例えば、ゲーム内でプレイヤーがジャンプを行う処理を作る場合、このInputActionsの中で「Jump」というアクションを作り、デバイス毎にボタンを割り当てて設定しておきます。

そして、実際にジャンプ処理を行いたいスクリプト側で、この「Jump」のアクション操作と紐づけてジャンプ処理を実行するように記述しておくことで、複数のデバイスの入力を一括で処理することができます。

このように、InputSystemはデバイスからの入力情報を受け取るだけでなく、それぞれのアクション毎に入力情報をまとめて管理することができます。

InputSystemの基本的な使い方

ここからは、実際にUnity上でInputSystemの基本的な使い方について紹介していきます。

プロジェクト内でInputSystemを設定する

InputSystemを使う場合、まずそのUnityプロジェクトでの入力システムとして、InputSystemが設定されている必要があります。

InputSystemが設定されているかどうかは、メニューの「Edit」から「ProjectSettings」を選択、

「Player」の下の方にある「Active Input Handing」の項目をチェックしておきます。

この項目でどの入力システムを使うか以下の3つから選択することができ、その内「Input System Package(New)」「Both」のどちらかが選択されていれば、InputSystemを使うことができます。

  • InputManager(Old):「InputManager」だけを使用する
  • Input System Package(New):「InputSystem」だけを使用する
  • Both:「InputManager」と「InputSystem」のどちらも使用する

ちなみに、Unity6ではデフォルトでInputSystemがインストールされていますが、過去のバージョン等で設定する際は、Package ManagerからInputSystemをインストールする必要があります。

また、選択肢の「InputManager(Old)」もしくは「Both」を選択しておくことで、「Input.GetAxis」「Input.GetKeyDown」などの以前からあるInputManagerを使った入力も行うことができます。

実際に、僕自身、新しいUnityのバージョンにしたら突然GetAxisが使えずに困ってしまったので、過去の入力方法を使いたい方はそちらを選択しましょう。

InputActionsの作成・設定

InputSystemを使う設定ができたら、次にアクション毎に入力操作を管理できるInputActionsを作成します。

このInputActionsは、使わなくても入力処理を作ることができますが、InputActionsを使ったほうが非常に簡単に入力操作を作れると思います。

ここでは、基本的なキャラクターのアクションとして、キーボードのWASDキーを押したら「移動」、スペースキーを押したら「ジャンプ」という2つのアクション操作をInputActionsに設定していきます。

InputActionsの作成

InputActionsの作成は、プロジェクトウィンドウの+ボタンから「InputActions」を選択します。

ここでは、「TestActions」という名前に変更しています。

なお、直近のUnityバージョンでは、以下のようにデフォルトでInputActionsが作成されているので、そちらをそのまま使っても問題ありません。

InputActionsの設定

次に、作成したInputActionsをダブルクリックして、以下のInputActionsEditorというものを開きます。

この画面では、

  • ActionMaps:どの対象のアクションの設定か
  • Actions:何のアクションに対する設定か
  • Binding:アクションを入力する実際の操作方法

の3つを設定していきます。

ActionMaps:どの対象のアクションの設定か

ActionMapsは、どの対象に対してのアクションを作るかをActionMap名で分けている項目となっていて、例えばプレイヤーの操作なら「Player」、UIの操作なら「UI」などで分けておきます。

今回は、プレイヤーの操作を作りたいので、ActionMapsの横の+ボタンを押して、作成されたActionMapに「Player」という名前を付けています。

Actions:何のアクションに対する設定か

Actionsの項目は、その入力操作で実行したいアクションとなる部分で、ここで設定したアクション単位で入力情報を受け取ることができます。

今回は、Actionsの横の+ボタンを押して、一つは移動操作用の「Move」、もう一つはジャンプ操作用の「Jump」という名称で作成しています。

次に、右側の「Action Properties」の部分でそれぞれのアクションに関しての定義を行うことができます。

このAction Propertiesは、そのアクション操作が行われた際に入力値をどのように受け取るのか、またボタンの長押しなどアクションの判定を定義することができます。

ここでは、以下のように設定しています。

Moveアクションの設定

まず、Moveのようなキャラクターの移動や視点などの操作の場合は、Action Typeを「Value」、Control Typeを「Vector2」にしてあげます。

これでそのアクションの入力操作が行われた時に、上下左右の2軸における入力をVector2型の値として受け取ることができるようになります。

Jumpアクションの設定

また、Jumpのように入力したらキャラクターのジャンプやダッシュが行われるというアクションなどの操作の場合は、Action Typeを「Button」にしてあげます。

すると、ボタンを押した際に入力を受け取ることができ、その処理を実行させることができます。

このAction Propertiesは、他にも様々な定義を行うことができますが、上記の2つが最もよく使われる設定になるかと思います。

Binding:アクションを入力する実際の操作方法

あとは、それぞれのアクションの右側にある+ボタンを押して、どの入力操作でそのアクションを行わせるかBindingという項目で設定していきます。

まず、「Move」のアクションの場合は、「Add Up¥Down¥Left¥Right Composite」を選択します。

これは、Composite Bindingと呼ばれるもので、それぞれのキーによる入力をまとめて一つの入力として管理できるものです。

このMoveのアクションは、WとSキーで上下のY軸、AとDキーで左右のX軸として、4つのキーを使って一つの入力値(Vector2型)を取得したいので、Composite Bindingを利用しています。

「Add Up¥Down¥Left¥Right Composite」を選択すると、以下のように「2D Vector」の中に「Up」「Down」「Left」「Right」が4つ作成されます。

それぞれの方向を選択し、Binding PropertiesのPathの箇所に「Keyboard」のキーを設定してあげます。

ちなみに、キーを設定する際は、選んでいくこともできますが、「Listen」を押してその後に実際の操作を入力するのが早いです。

次に、「Jump」のアクションの場合は、一つのキーによる入力が行えれば良いので、「Add Binding」を選択します。

そして、先ほどと同様にBinding PropertiesのPathの箇所に、ジャンプ操作としてスペースキーを設定してあげます。

これで、InputActionsの設定を行うことができたので、「Save Asset」を押して保存しておきましょう。

なお今回は、キーボード操作だけを設定していますが、他デバイス(コントローラーなど)の入力も設定する場合は、同じアクションの中にBindingを追加して設定します。

InputActionsクラスの作成

InputActionsの設定ができたら、設定したアクションをスクリプトで受け取れるように、InputActionsのクラスを作成しておきます。

アセットフォルダからInputActionsのアセットを選択した状態で、インスペクターウィンドウの「Generate C# Class」にチェックを入れます。

すると、C#のクラス名やファイル名を設定する項目が表示されます。

設定内容を確認して「Apply」を押すと、アセットフォルダ内にInput ActionsのC#ファイルが作成されます。

これで、InputActionsのクラスを作成することができました。

スクリプトから入力操作の処理を作る

InputActionsの設定ができたら、スクリプトからアクションが入力された際の処理を作っていきます。

ここでは、以下のカプセル型のオブジェクトをプレイヤーとしておき、RigidbodyおよびCapsuleColliderのコンポーネントを紐づけておきます。

そして、このオブジェクトに以下のスクリプトを紐づけておきます。

using UnityEngine;
using UnityEngine.InputSystem;  // InputSystemを利用する記述

public class PlayerController : MonoBehaviour
{
    Rigidbody rb;
    float speed = 15.0f;
    float jump = 400f;
    bool isJumping;

    // Moveの入力操作による値を取得
    Vector2 moveValue;

    // InputActions型の変数を宣言
    TestActions action;

    void Start()
    {
        rb = GetComponent<Rigidbody>();

        // InputActionsのインスタンスを生成
        action = new TestActions();

        // それぞれタイミングでのコールバック処理を登録
        action.Player.Move.performed += OnMove; // Moveの入力が行われた時
        action.Player.Move.canceled += OnMove;  // Moveの入力が無くなった時
        action.Player.Jump.performed += OnJump; // Jumpの入力が行われた時

        // InputActionsを手動で有効化する
        action.Enable();
    }

    void OnDisable()
    {
        // InputActionsを手動で無効化する
        action.Disable();
    }

    void FixedUpdate()
    {
        // 移動処理
        if (moveValue != Vector2.zero)
        {
            rb.AddForce(moveValue.x * speed, 0, moveValue.y * speed);
        }
    }

    // Moveのアクションが入力された際に行う処理
    void OnMove(InputAction.CallbackContext context)
    {
        moveValue = context.ReadValue<Vector2>();   // 入力されたVector2型の値を取得
    }

    // Jumpのアクションが入力された際に行う処理
    void OnJump(InputAction.CallbackContext context)
    {
        // ジャンプ処理
        if (!isJumping)
        {
            rb.AddForce(transform.up * jump);
            isJumping = true;
        }
    }

    // 接地判定の処理
    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Ground" && isJumping)
        {
            isJumping = false;
        }
    }
}

まず、2行目でInputSystemをスクリプトから利用するため、以下のように記述しておきます。

using UnityEngine.InputSystem;

次に、15行目で先ほど作成したTestActionsクラスの変数を宣言して、22行目のStartメソッドの中でこの変数にnewキーワードで生成したインスタンスを代入しています。

// 作成したInputActions型の変数
TestActions action;

// インスタンスを生成
action = new TestActions();

そして、25行目から27行目でそれぞれのアクションに対する入力操作が行われた際に、実行したい処理のメソッドをコールバックに登録しています。

// それぞれタイミングでのコールバック処理を登録
action.Player.Move.performed += OnMove; // Moveの入力が行われた時
action.Player.Move.canceled += OnMove;  // Moveの入力が無くなった時
ction.Player.Jump.performed += OnJump; // Jumpの入力が行われた時

コールバック処理を登録する際は、

InputActionsの変数名.ActionMap名.Action名.入力操作の状態 += 登録したいメソッド名;

と記述してあげます。

入力操作の状態は、以下の3つから設定することができます。

  • started:0(無操作)から入力が行われた状態
  • performed:閾値以上の入力が行われた状態
  • canceled:入力がある状態から0もしくは閾値未満になった状態

「Move」のアクションは、入力された時(performed)入力が離れた時(canceled)の2つの状態で処理を行えるようにして、「OnMove」というメソッドを登録しています。

「Jump」のアクションは、入力された際にジャンプ処理が行えれば良いので、performedだけを指定して「OnJump」というメソッドを登録しています。

このコールバックに登録するそれぞれのメソッドは、引数にCallbackContextという構造体の変数を指定する必要があり、その変数を使って入力情報を受け取ることができます。

そのため、49行目でOnMoveの処理内容を以下のように記述していて、moveValueというVector2型の変数を使って、CallbackContext型の変数からReadValueメソッドで入力値を取得しています。

void OnMove(InputAction.CallbackContext context)
{
    moveValue = context.ReadValue<Vector2>();   // 入力されたVector2型の値を取得
}

実際に行う移動処理は、FixUpdate内の42行目で記述していて、この取得したmoveValueの値からAddForceメソッドで移動処理を作っています。

if (moveValue != Vector2.zero)
{
    rb.AddForce(moveValue.x * speed, 0, moveValue.y * speed);
}

OnJumpの処理は55行目で以下のように記述していて、このメソッド内で上向きの力を加えてジャンプ処理を行っています。

void OnJump(InputAction.CallbackContext context)
{
    // ジャンプ処理
    if (!isJumping)
    {
        rb.AddForce(transform.up * jump);
        isJumping = true;
    }
}

また、InputActionsを使う際、手動で有効化と無効化の処理を記述してあげる必要があります。

そこで、30行目でEnableメソッドを使ってInputActionsを有効化する処理をStartメソッド内で記述しています。

// InputActionsを手動で有効化する
action.Enable();

そして、36行目のOnDisableの中でDisableメソッドを使ってInputActionsを無効化する処理を記述しています。

// InputActionsを手動で無効化する
action.Disable();

これでゲームを実行してみると、

それぞれの入力操作に応じて、ちゃんと処理が実行されているのが分かります。

なお、InputActionsを使う記述やコールバックの処理は、アクションが多ければ多いほど設定が複雑になるため、より簡単に入力処理を作る場合はPlayerInputというコンポーネントを使うのが便利です。

まとめ

このページでは、UnityのInputSystemという入力システムについて、どんな仕組みなのか、基本的な使い方までをまとめていきましたが、いかがでしたでしょうか?

InputSystemは、InputManagerに変わる新しい入力システムで、直近のUnityではデフォルト設定になっているシステムです。

このInputSystemの特徴として、InputActionsというアクションごとに複数のデバイスからの入力操作を管理することができます。

また、ボタンの長押し操作や複数のボタン同時入力なども管理することができるので、より拡張性の高いシステムとなっています。

最後までお読みいただきまして、ありがとうございました!

コメント