【Unity】Player InputでInput Systemの入力を取得する

こじゃらこじゃら

Input SystemでPlayer Inputを使いたいけど、使い方が分からないの…

このはこのは

具体例を交えて解説していくね。

Input Systemで提供されているPlayer Inputの使い方の解説です。

Player Inputは、Input Systemの入力を仲介するコンポーネントで、Input Actionの入力をスクリプト側に通知する役割を持ちます。

本記事では、次のようにオブジェクトを移動させることを例にとって、Player Inputの使い方を解説していきます。

動作環境
  • Unity 2021.2.4f1
  • Input System 1.1.1

スポンサーリンク

前提条件

予めInput Systemがインストールされ、有効化されているものとします。ここまでの手順が分からない方は、以下記事をご覧ください。

また、次のようにシーンにオブジェクトが配置されているものとします。

本記事で紹介するサンプルでは、黄色のキューブを移動させることとします。

Player Inputの適用

動かす対象のオブジェクトにPlayer Inputコンポーネントをアタッチします。オブジェクトを選択した状態でインスペクターのAdd Componentボタンから行ってください。

アタッチすると、次のようなPlayer Inputプロパティがインスペクターに表示されます。

この中で重要な設定はActionsBehaviorです。

まず、Actions項目Input Actionアセットを指定します。Input ActionはCreate Actions…ボタンから新規作成することも可能です。

本記事ではInput Actionアセットを新規作成することとします。

Actions項目を設定して次のようなプロパティ表示に変われば成功です。

Player Inputプロパティの説明

プロパティの各設定項目について説明します。詳細は以下リファレンスページで解説されています。

参考:GameObject components for input | Input System | 1.2.0

Actions

Player Inputが参照するInput Actionアセットを指定します。

Actions項目下には、どのスキームを使用するかを設定する項目があります。ここで言うスキームとは、キーボード&マウスや、ゲームパッド、タッチパネルなどのコントローラーの種類のことを指します。

例えば、スキームがGamepadの場合、Gamepadスキームが有効になっているActionのみ有効になります。

Actionとは、操作の単位で、例えば移動や攻撃などを自由に定義することができるものです。Actionの基本概念と使い方が分からない方は、以下記事をご覧ください。

Default Scheme

デフォルトで使用するスキームを指定します。

<Any>が指定された場合は、使用するスキームが自動的に決定されます。

参考:Input Bindings | Input System | 1.2.0

例えば、キーボードとマウスが接続されている環境なら、スキームはKeyboardMouseになります。

Auto-Switch

使用中のスキームが使用不可になったとき、別のスキームに切り替えるかどうかの設定です。

Defualt Map

Input ActionアセットのどのMapをデフォルトで使用するかを指定します。MapとはActionの集まりの単位で、Input Actionアセット編集ウィンドウの以下の部分に相当します。

UI Input Module

UIの操作に使うモジュールを指定します。UIをPlayer Input経由で操作させたい場合などに役立ちます。UIを操作しない場合は何も指定しなくても問題ありません。

Camera

プレイヤーに関連付けるカメラを指定します。複数プレイヤーの画面分割をするときに使います。

Behavior

スクリプト側に通知する方法を次の4種類から指定します。

  • Send Messages
    • Component.SendMessageメソッドを使ってスクリプトに通知します。
  • Broadcast Messages
    • Component.BroadcastMessageメソッドを使ってスクリプトに通知します。
  • Invoke Unity Events
    • UnityEventを通じて通知します。
  • Invoke C Sharp Events
    • C#のデリゲートを通じて通知します。

設定によって参照元のスクリプトのコードが異なります。

次に、それぞれの設定における使い方について、例を示しながら解説していきます。

Send Messages/Broadcast Messagesを設定して通知を受け取る

Moveアクションの通知を受け取って、オブジェクトを移動させるサンプルスクリプトです。

SendMessageExample.cs
using UnityEngine;
using UnityEngine.InputSystem;

public class SendMessageExample : MonoBehaviour
{
    private Vector3 _velocity;

    // 通知を受け取るメソッド名は「On + Action名」である必要がある
    private void OnMove(InputValue value)
    {
        // MoveActionの入力値を取得
        var axis = value.Get<Vector2>();

        // 移動速度を保持
        _velocity = new Vector3(axis.x, 0, axis.y);
    }

    private void Update()
    {
        // オブジェクト移動
        transform.position += _velocity * Time.deltaTime;
    }
}

上記スクリプトをSendMessageExample.csという名前で保存し、プレイヤーオブジェクトにアタッチします。

また、Player InputコンポーネントのBehaviorSend MessagesまたはBroadcast Messagesに設定します。

BehaviorにSend Messagesが設定されている場合は、Player Inputがアタッチされているオブジェクトにアタッチする必要があります。

Broadcast Messagesが設定されている場合は、Player Inputがアタッチされているオブジェクトまたはその子オブジェクトにアタッチする必要があります。

注意

SendMessage系のメソッドが内部的に発行されるため、パフォーマンスに影響が出る可能性があることにご注意ください。特に、BroadcastMessageメソッドは子階層のコンポーネントに対してメッセージを送信するため、その分負荷が高くなります。

実行結果

スクリプトの解説

Input Systemの名前空間をusingします。

using UnityEngine.InputSystem;

Player Inputから通知を受け取るためには、「On + Action名」という名前のメソッドを定義する必要があります。

例では、Moveという名前のAction通知を受け取るために、OnMoveメソッドを定義しています。

// 通知を受け取るメソッド名は「On + Action名」である必要がある
private void OnMove(InputValue value)
{
    // MoveActionの入力値を取得
    var axis = value.Get<Vector2>();

    // 移動速度を保持
    _velocity = new Vector3(axis.x, 0, axis.y);
}

引数は、入力値が格納されるInputValue型です。

参考:Class InputValue | Input System | 1.2.0

入力値はGetメソッドから取得できます。

通知は毎フレーム発行される訳ではないため、_velocity変数に速度を保持して、Updateイベント内移動処理を行うようにしています。

private void Update()
{
    // オブジェクト移動
    transform.position += _velocity * Time.deltaTime;
}

Invoke Unity Eventsを設定して通知を受け取る

通知を受け取るスクリプトの例です。

UnityEventExample.cs
using UnityEngine;
using UnityEngine.InputSystem;

public class UnityEventExample : MonoBehaviour
{
    private Vector3 _velocity;

    // メソッド名は何でもOK
    // publicにする必要がある
    public void OnMove(InputAction.CallbackContext context)
    {
        // MoveActionの入力値を取得
        var axis = context.ReadValue<Vector2>();

        // 移動速度を保持
        _velocity = new Vector3(axis.x, 0, axis.y);
    }

    private void Update()
    {
        // オブジェクト移動
        transform.position += _velocity * Time.deltaTime;
    }
}

このスクリプトをUnityEventExample.csという名前で保存し、プレイヤーオブジェクトにアタッチします。

また、Player InputコンポーネントのBehaviorInvoke Unity Eventsを設定します。

すると、Events項目が出現するため、該当するイベントの+ボタンより通知を受け取るスクリプトのメソッドを指定します。

実行結果は先と同じため割愛します。

スクリプトの解説

通知を受け取るためのメソッドは次の形式になっています。

// メソッド名は何でもOK
// publicにする必要がある
public void OnMove(InputAction.CallbackContext context)

InputAction.CallbackContext型の引数を受け取る点が異なります。

入力値はReadValueメソッドから取得します。

// MoveActionの入力値を取得
var axis = context.ReadValue<Vector2>();

Invoke C Sharp Eventsを設定して通知を受け取る

C#標準のAction経由で通知を受け取るようにスクリプトを実装します。

CSharpEventExample.cs
using UnityEngine;
using UnityEngine.InputSystem;

[RequireComponent(typeof(PlayerInput))]
public class CSharpEventExample : MonoBehaviour
{
    private PlayerInput _playerInput;
    private Vector3 _velocity;

    private void Awake()
    {
        _playerInput = GetComponent<PlayerInput>();
    }

    private void OnEnable()
    {
        if (_playerInput == null) return;

        // デリゲート登録
        _playerInput.onActionTriggered += OnMove;
    }

    private void OnDisable()
    {
        if (_playerInput == null) return;

        // デリゲート登録解除
        _playerInput.onActionTriggered -= OnMove;
    }

    private void OnMove(InputAction.CallbackContext context)
    {
        // Move以外は処理しない
        if (context.action.name != "Move")
            return;

        // MoveActionの入力値を取得
        var axis = context.ReadValue<Vector2>();

        // 移動速度を保持
        _velocity = new Vector3(axis.x, 0, axis.y);
    }

    private void Update()
    {
        // オブジェクト移動
        transform.position += _velocity * Time.deltaTime;
    }
}

このスクリプトをCSharpEventExample.csという名前で保存し、プレイヤーオブジェクトにアタッチします。

また、BehaviorInvoke C Sharp Eventsを指定します。

実行結果は1つ目の例と同じため割愛します。

スクリプトの解説

通知を受け取るためのデリゲートは、onActionTriggeredプロパティより追加できます。

// デリゲート登録
_playerInput.onActionTriggered += OnMove;

さいごに

Player Inputを使うと、Actionからの入力受け取りを簡単に実装できます。

入力値は、Player Input側から通知を受け取る形で取得できます。

特にUnityEvent経由で入力をやり取りできるようにすれば、拡張性が高まり、コードの見通しも良くなるためお勧めです。

参考サイト

スポンサーリンク