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

こじゃらこじゃら

Input Systemで「Press any key」のように、どれかのボタンが押されたかどうか判定したいの…

このはこのは

Input ActionのControl Path設定で簡単に実現できるわ。

Input Systemでゲームパッドやキーボードなどの任意ボタンが押されたかどうかを判定する方法の解説記事です。

結論を述べると、次のようにInput Actionに設定するBindingなどのControl PathLayout名ワイルドカードを用いると実現可能です。

ゲームパッドの任意ボタンを表すControl Path

<Gamepad>/<Button>

スティック入力も含む任意入力

<Gamepad>/*

また、キーボード入力では、anyKeyという専用キーも存在します。

キーボードの任意キーを表すControl Path

<Keyboard>/anyKey

本記事では、このような任意キー入力を判定する方法について、具体例と共にいくつか紹介します。

動作環境
  • Unity 2022.3.0f1
  • Input System 1.5.1

スポンサーリンク

前提条件

事前にInput Systemがインストールされ、有効化されているものとします。

ここまでの手順が分からない方は、以下記事を参考にセットアップを済ませてください。

また、本記事を読み進めるにあたっては、Input ActionおよびControl Pathの仕組みを押さえておくと理解がスムーズです。

Input Actionの基本的な仕組みは以下記事で解説しています。

Control Pathの仕組みについては以下記事で解説しています。

任意入力を判定する

ActionのBindingに指定するControl Pathには、次のように具体的なControl名を指定する事が多いかもしれません。

ゲームパッドの左トリガー入力の例

<Gamepad>/leftTrigger

しかし、ゲームパッドなどのデバイス配下のControl「Button」というLayout名を指定すると、ゲームパッド配下のButton型のControl全体が入力対象となります。

ゲームパッドの全てのボタンを表すControl Path

<Gamepad>/<Button>

メモ

Control Pathに「<」「>」で囲んで指定する文字列はLayout名を表します。ゲームパッドなら「<Gamepad>」、ボタンなら「<Button>」、スティックなどの2軸入力なら「<Vector2>」となります。

参考:Class InputControlPath | Input System | 1.5.1

特定のLayoutに限定せず、スティックなどButton以外のLayoutも含めた「全て」の入力を対象とする場合、アスタリスク「*」を指定できます。

ゲームパッドの全ての入力を表すControl Path

<Gamepad>/*

サンプルスクリプト

ゲームパッドの任意入力を受け取ったらログ出力する例です。ボタンのみの判定およびスティックを含めた全入力の判定の2パターンでチェックしています。

GamepadExample.cs
using UnityEngine;
using UnityEngine.InputSystem;

public class GamepadExample : MonoBehaviour
{
    private InputAction _anyButtonAction;
    private InputAction _anyAction;

    private void Awake()
    {
        // 任意ボタンのAction作成
        _anyButtonAction = new InputAction(
            "AnyButton",
            InputActionType.Button,
            "<Gamepad>/<Button>"
        );
        // 任意入力のAction作成
        _anyAction = new InputAction(
            "Any",
            InputActionType.Button,
            "<Gamepad>/*"
        );

        // コールバック登録
        _anyButtonAction.performed += OnAnyButton;
        _anyAction.performed += OnAny;
    }

    private void OnDestroy()
    {
        // コールバック解除
        _anyButtonAction.performed -= OnAnyButton;
        _anyAction.performed -= OnAny;

        // Actionの破棄
        _anyButtonAction.Dispose();
        _anyAction.Dispose();
    }

    private void OnEnable()
    {
        // Actionの有効化
        _anyButtonAction.Enable();
        _anyAction.Enable();
    }

    private void OnDisable()
    {
        // Actionの無効化
        _anyButtonAction.Disable();
        _anyAction.Disable();
    }

    // 任意ボタンが押されたときの処理
    private void OnAnyButton(InputAction.CallbackContext context)
    {
        // Device名とControl名をログ出力
        print($"OnAnyButton() : {context.control.device.name} {context.control.name}");
    }

    // 任意入力(スティック入力含む)があったときの処理
    private void OnAny(InputAction.CallbackContext context)
    {
        // Device名とControl名をログ出力
        print($"OnAny() : {context.control.device.name} {context.control.name}");
    }
}

上記をGamepadExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチすると機能するようになります。

注意

当サンプルを動かすためには、ゲームパッドが予め接続されている必要があります。

実行結果

ゲームパッドが接続されている状態で、ゲームパッドのボタンを押すと、ゲームパッドのデバイス名とControl名がログ出力されます。

この時、OnAnyButtonとOnAny両方が呼ばれていることが確認できます。

スティックを倒すと、任意ボタン入力は受け取らなくなるため、OnAnyだけのログが出力されます。

スクリプトの説明

ゲームパッドの任意ボタン、スティック含めた任意入力のActionを以下処理でスクリプトから生成・初期化しています。

// 任意ボタンのAction作成
_anyButtonAction = new InputAction(
    "AnyButton",
    InputActionType.Button,
    "<Gamepad>/<Button>"
);
// 任意入力のAction作成
_anyAction = new InputAction(
    "Any",
    InputActionType.Button,
    "<Gamepad>/*"
);

参考:Class InputAction | Input System | 1.5.1

上記ActionはAction TypeをButtonとして初期化しているため、入力値の大きさがPress Point以上になった瞬間performedコールバックが発火します。

これを受け取るようにコールバック登録しています。

// コールバック登録
_anyButtonAction.performed += OnAnyButton;
_anyAction.performed += OnAny;

登録したコールバックの処理では、次のようにDevice名(ゲームパッド名など)およびControl名(ボタン名など)をログ出力しています。

// 任意ボタンが押されたときの処理
private void OnAnyButton(InputAction.CallbackContext context)
{
    // Device名とControl名をログ出力
    print($"OnAnyButton() : {context.control.device.name} {context.control.name}");
}

// 任意入力(スティック入力含む)があったときの処理
private void OnAny(InputAction.CallbackContext context)
{
    // Device名とControl名をログ出力
    print($"OnAny() : {context.control.device.name} {context.control.name}");
}

anyKeyを用いてキーボードの任意キー入力を判定する

キーボードの任意キーの入力を受け取る際も前述の方法で実現できますが、anyKeyと言う任意キー専用のControlが使えます。

<Keyboard>/anyKey

参考:Class AnyKeyControl | Input System | 1.5.1

単一のControlだけで完結できるのが特徴です。ただし、どのキーが押されたかを判定できない点に注意する必要があります。

サンプルスクリプト

以下、キーボードの任意キーが押されたらログ出力する例です。

AnyKeyExample.cs
using System;
using UnityEngine;
using UnityEngine.InputSystem;

public class AnyKeyExample : MonoBehaviour
{
    private InputAction _anyKeyAction;

    private void Awake()
    {
        // 任意キーのAction作成
        _anyKeyAction = new InputAction(
            "AnyKey",
            InputActionType.Button,
            "<Keyboard>/anyKey"
        );

        // コールバック登録
        _anyKeyAction.performed += OnAnyKey;
    }

    private void OnDestroy()
    {
        // コールバック解除
        _anyKeyAction.performed -= OnAnyKey;

        // Actionの破棄
        _anyKeyAction.Dispose();
    }

    private void OnEnable()
    {
        // Actionの有効化
        _anyKeyAction.Enable();
    }

    private void OnDisable()
    {
        // Actionの無効化
        _anyKeyAction.Disable();
    }

    // 任意キーが押されたときの処理
    private void OnAnyKey(InputAction.CallbackContext context)
    {
        // Device名とControl名をログ出力
        print($"OnAnyKey() : {context.control.device.name} {context.control.name}");
    }
}

上記をAnyKeyExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチすると機能します。

実行結果

キーボードのいずれかのキーを押すとログ出力されます。

前述の例と違い、どのキーが押されたかまでは判別できません。

スクリプトの説明

前述の例と違う部分は以下初期化処理です。

// 任意キーのAction作成
_anyKeyAction = new InputAction(
    "AnyKey",
    InputActionType.Button,
    "<Keyboard>/anyKey"
);

BindingのControl Path「<Keyboard>/anyKey」を指定しています。

複数デバイスに対応する場合

複数のデバイスの任意入力を受け取りたい場合は、それぞれのデバイスの任意キーのControl Pathを保持したBindingを複数登録すれば良いです。

例えば、ゲームパッドキーボードの任意キーを対象とする場合は、次のControl PathのBindingを2つ追加します。

  • <Gamepad>/<Button>
  • <Keyboard>/anyKey

サンプルスクリプト

ゲームパッドとキーボードの任意キーが押されたらログ出力する例です。

MultipleDeviceExample.cs
using UnityEngine;
using UnityEngine.InputSystem;

public class MultipleDeviceExample : MonoBehaviour
{
    private InputAction _anyButtonAction;

    private void Awake()
    {
        // Action作成
        _anyButtonAction = new InputAction(
            "AnyButton",
            InputActionType.Button
        );
        // ゲームパッドの任意ボタンとキーボードの任意キーをバインド
        _anyButtonAction.AddBinding("<Gamepad>/<Button>");
        _anyButtonAction.AddBinding("<Keyboard>/anyKey");

        // コールバック登録
        _anyButtonAction.performed += OnAnyButton;
    }
    
    private void OnDestroy()
    {
        // コールバック解除
        _anyButtonAction.performed -= OnAnyButton;

        // Actionの破棄
        _anyButtonAction.Dispose();
    }
    
    private void OnEnable()
    {
        // Actionの有効化
        _anyButtonAction.Enable();
    }
    
    private void OnDisable()
    {
        // Actionの無効化
        _anyButtonAction.Disable();
    }
    
    // 任意ボタンが押されたときの処理
    private void OnAnyButton(InputAction.CallbackContext context)
    {
        // Device名とControl名をログ出力
        print($"OnAnyButton() : {context.control.device.name} {context.control.name}");
    }
}

上記をMultipleDeviceExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチします。

実行結果

次のようにゲームパッドとキーボードの両方の入力に対応していることが確認できます。

スクリプトの説明

Bindingを複数登録したいため、InputActionのコンストラクタではなくAddBinding拡張メソッドそれぞれのデバイスのControl Pathを持ったBindingを追加しています。

// Action作成
_anyButtonAction = new InputAction(
    "AnyButton",
    InputActionType.Button
);
// ゲームパッドの任意ボタンとキーボードの任意キーをバインド
_anyButtonAction.AddBinding("<Gamepad>/<Button>");
_anyButtonAction.AddBinding("<Keyboard>/anyKey");

参考:Class InputActionSetupExtensions | Input System | 1.5.1

それ以外はこれまでの例と一緒です。

さいごに

任意の入力を扱いたい場合は、Control Pathに具体的なControl名ではなくLayout名やワイルドカードなどを指定すると実現可能です。

キーボードに限り、anyKeyというControl名の専用入力があるためこちらを使えば良いでしょう。

関連記事

参考サイト

スポンサーリンク