【Unity】Input Systemでプレイヤーに複数デバイスを割り当てる

こじゃらこじゃら

シングルプレイ、またはローカルマルチで一人のプレイヤーに複数コントローラーを割り当てるにはどうすればいいの?

このはこのは

複数デバイスを割り当てたControl Schemeを用意して適用すれば良いわ。

Input SystemのPlayer Input使用下において、1プレイヤーに複数デバイスを割り当てる方法の解説記事です。

次のような使い方を想定します。

想定する場面
  • キーボード&マウスでプレイヤーを操作する
  • ゲームパッドとマウスを割り当てる(モンゴリアンスタイル)
  • タッチパネルと物理キーボードを使用する
  • 複数プレイヤーに複数コントローラーを割り当てる

このようなデバイスの組み合わせは、Input Action AssetのControl Schemeの設定から自由に変えられます。

参考:Input Action Assets | Input System | 1.7.0

本記事では、各プレイヤーに複数デバイスを割り当てる方法について、概念的な部分から順を追って解説していきます。また、使用上における注意点についても触れておきます。

UCL UCL

この作品はユニティちゃんライセンス条項の元に提供されています

動作環境
  • Unity 2023.2.16f1
  • Input System 1.7.1

スポンサーリンク

前提条件

事前にInput Systemパッケージがインストールされ、有効になっているものとします。

導入手順および基本的な使い方は以下記事で解説しています。

また、Player Inputで入力を受け取ることが前提となります。

本記事では、以下のようにPlayer Inputがセットアップされたプレイヤーに対して複数デバイスによる操作を適用していくものとして解説を進めます。

空シーンでも最低限の動作検証ができるように、コンソールログから確認する例も示します。

Control Schemeとデバイス割り当ての仕組み

複数デバイスを理解するために、まずControl Schemeの仕組みについて軽く触れておきます。説明不要な方は適用手順の項目まで読み飛ばしていただいて構いません。

ゲームパッドやキーボード&マウスなど、どのデバイスの組み合わせで操作するかの設定は、Control Schemeとして定義できます。

Control Schemeは通常、想定される操作スタイルの組み合わせだけ定義します。

Control Schemeの定義例

そして、ゲーム実行時に予め定義されたControl Schemeのうちいずれか1つを選択します。

例えば、キーボード&マウスでキャラクターを操作したい場合、上図のKeyboard&Mouseという名前のControl Schemeが選択されます。

Control Schemeの選択イメージ

どのControl Scheme(デバイスの組み合わせ)を選択して使用するかは、自動または手動で設定できます。

  • 入力があったデバイスに基づいてControl Schemeを自動選択・切替する
  • 予め決められたControl Schemeを選択する
  • スクリプトから途中でControl Schemeを切り替える

自動選択はシングルプレイヤーモード時に限り使用可能で、入力があったデバイスのControl Schemeに自動的に切り替わる挙動になっています。

参考:Class PlayerInput | Input System | 1.7.0

注意

複数のControl Schemeを同時選択することはできません。特にシングルプレイヤーで自動切替を有効にしている場合、複数スキームのデバイスを同時に操作すると、次のような不都合が生じるので注意が必要です。

  • 高速にスキームが切り替わるような挙動が生じる
  • いずれか一方のデバイス入力しか受け取れなくなる

ローカルマルチで複数プレイヤーが参加する場合は、各プレイヤーにいずれかのスキームが割り当てられます。

デバイス割り当ての例

入力ソースに対するControl Schemeの割り当ては、Input Action AssetのAction(移動、ジャンプなどの操作)のBinding毎に設定できます。

注意

各BindingにControl Schemeを設定する形になりますが、この時BindingがControl Schemeで設定されている以外のデバイスだった場合は入力を受け取れなくなることに注意が必要です。

例えば、ゲームパッドの左スティック入力のBindingに対してKeyboard&MouseというControl Schemeを設定してしまうと、スティック入力が全く受け取れなくなります。

複数デバイス割り当て手順

ここから先は、実際にControl Schemeに複数デバイスを割り当てる手順の解説に入ります。

例では、次の複数と単一のデバイスの組み合わせのControl Schemeを定義することとします。

  • キーボード&マウス
  • ゲームパッド&マウス
  • ゲームパッド

また、上記Control Schemeに対して、以下のような操作を割り当てるものとします。

  • キーボード&マウス
    • 移動 – WASDキー(キーボード)
    • ジャンプ – スペースキー(キーボード)
    • 視点変更 – マウス移動量(マウス)
  • ゲームパッド&マウス
    • 移動 – 左スティック(ゲームパッド)
    • ジャンプ – Lショルダー(ゲームパッド)
    • 視点変更 – マウス移動量(マウス)
  • ゲームパッド
    • 移動 – 左スティック(ゲームパッド)
    • ジャンプ – Southボタン(ゲームパッド)
    • 視点変更 – 右スティック(ゲームパッド)

Input Action Assetの作成

まず、作成Input Action Assetが作成されていなければ、プロジェクトウィンドウの右クリック > Create > Input Actionsから新規作成します。

例では、「Game」という名前のInput Action Assetとしました。

Control Schemeの作成

Input Action Assetをダブルクリックしてウィンドウを開き、左上のControl SchemeのボタンからAdd control schemeを選択し、Scheme Nameスキーム名を、その下のリストレイアウト(KeyboardやMouseなど)を追加してSaveボタンを押します。

以下は「Keyboard&Mouse」という名前のControl Schemeを作成し、キーボードとマウスをレイアウト(デバイス)として追加する例です。

追加されたControl Schemeは、先ほどの左上のControl Schemeのボタンから表示されるメニューから確認できます。

同様に、他のControl Schemeも追加します。例では「Gamepad&Mouse」「Gamepad」という名前のControl Schemeを追加して設定するものとします。

Action MapとActionの定義

Control Schemeを作成出来たら、次は各種操作(Action)の定義をしていきます。

まず、Mapが作成されていなければ、適当な名前のMapを作成します。例では「Player」としました。

次に、Map配下に必要なActionを定義します。以下は「Move」という名前のActionを定義する例です。

そして、そのAction配下にに必要なキー割り当て(Binding)を定義していきます。以下はWASDキーを設定する例です。

そして、定義したBindingを選択して、User in control scheme項目該当するControl Schemeにチェックを入れます。

他のスキームの操作も同時に設定します。例ではゲームパッドの左スティックが必要なので、それを定義しています。

他のActionも同様に設定してください。例ではジャンプ視点変更操作のActionを定義しています。

Player Input側の設定

ここまで設定したInput Action Assetは、プレイヤー操作用のPlayer Inputコンポーネントに設定する必要があります。未設定の場合は、Player InputのActions項目に指定してください。

また、操作対象のオブジェクトが無い場合は、後述する検証用スクリプトの手順を実施してください。

検証用スクリプト(必要ならば)

シーンのセットアップが済んでいないが、入力だけ確認したい場合は、以下スクリプトでコンソールログから確認してください。

CheckInputsExample.cs
using UnityEngine;
using UnityEngine.InputSystem;

public class CheckInputsExample : MonoBehaviour
{
    [SerializeField] private PlayerInput _playerInput;

    [SerializeField] private string _moveActionName = "Move";
    [SerializeField] private string _jumpActionName = "Jump";
    [SerializeField] private string _lookActionName = "Look";

    private void Start()
    {
        // UnityEvent経由で受け取るように設定
        _playerInput.notificationBehavior = PlayerNotifications.InvokeUnityEvents;
        
        // PlayerInputのイベント登録
        _playerInput.actions[_moveActionName].performed += OnMove;
        _playerInput.actions[_jumpActionName].performed += OnJump;
        _playerInput.actions[_lookActionName].performed += OnLook;
    }

    private void OnDestroy()
    {
        // PlayerInputのイベント解除
        _playerInput.actions[_moveActionName].performed -= OnMove;
        _playerInput.actions[_jumpActionName].performed -= OnJump;
        _playerInput.actions[_lookActionName].performed -= OnLook;
    }

    // 移動入力
    private void OnMove(InputAction.CallbackContext context)
    {
        if (!context.started)
        {
            print($"[Move/{context.control.device.name}]: {context.ReadValue<Vector2>()}");
        }
    }

    // ジャンプ入力
    private void OnJump(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            print($"Jump/{context.control.device.name}]");
        }
    }

    // 視点移動入力
    private void OnLook(InputAction.CallbackContext context)
    {
        if (!context.started)
        {
            print($"[Look/{context.control.device.name}]: {context.ReadValue<Vector2>()}");
        }
    }
}

上記をCheckInputsExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにPlayer Inputと上記スクリプトを追加し、動画の通り設定を行ってください。

実行結果

コンソールログ版の場合は、次のように入力されたActionとデバイス名が表示されれば成功です。

動画では分かりやすさのため、入力状態を可視化しています。

キャラクター操作でも入力を受け取れさえすれば、移動やジャンプなどの処理はそのまま動くでしょう。

Tips

現在選択されているスキームは、実行時にPlayer InputコンポーネントのインスペクターのDebug > Control Schemeから確認可能です。

意図しないControl Schemeに切り替わるケース

前述の例では、Control Schemeの切り替えを自動で行っていたため意図しないスキームに切り替わることがあります。

例えばGamepad&MouseGamepadのスキームでゲームパッド入力のようにControl(スティックなど)が被っていた場合どちらが選択されるか曖昧になります。

このような場合、自動切換を無効化して、明示的にスキームを指定することで解決できます。

ローカルマルチ時の挙動について

Player Input Managerなどを使用した複数人でのローカルマルチプレイ時でも、複数デバイスを割り当てる方法は基本的に変わりません。

ただし、シングルプレイで使用可能だったスキームの自動切換えは、マルチプレイヤー時では無効になります。

参考:Class PlayerInput | Input System | 1.7.0

実際のスキームの割り当ては、基本的にプレイヤーの入室時に決定されます。

もし途中でスキームを変更したい場合、次のように明示的にControl Schemeを変更すれば良いです。

PlayerInput playerInput;

・・・(中略)・・・

// 指定したスキームにスクリプトから切り替え
// 使用するデバイスも渡す必要あり
playerInput.SwitchCurrentControlScheme(
    "Keyboard&Mouse",
    Keyboard.current,
    Mouse.current
);

参考:Class PlayerInput | Input System | 1.7.0

さいごに

1プレイヤーに複数のコントローラーなどのデバイスを割り当てるには、Control Schemeに必要なデバイスを指定すれば良いです。

シングルプレイヤーモードの場合、スキームの自動切換えが有効になっていると入力があったControl Schemeに切り替わるため、一見すると複数デバイスが使えるが、同時操作が出来ないような挙動になるので注意が必要です。

ローカルマルチでもこの考え方は変わりません。

関連記事

参考サイト

スポンサーリンク