【Input System】ゲーム内キーコンフィグをリバインディングで簡単に実装【Unity】

Input System サムネ

Unityゲームエンジンの入力システム「 Input System」でゲーム内のキーコンフィグ、つまりゲーム内でキーを変更する処理を実装する方法を紹介します。

従来のInput Managerは、そもそもキーのバインドができないため実装不可能でした。そのため、ゲーム内キーコンフィグを実装するには一からInput Managerもどきを実装する必要がありました。

Input Systemはゲーム内でキーの再バインディングを行うことで実装が可能です。そのため、使う側は何をバインディングしたかを全く意識することなく利用が可能です。

リバインディングを実装

では、サンプル例を用意します。

空のGameObjectを作成しPlayerInputコンポーネントを追加、Creater Actionsで予め簡単な設定が完了しているInputActionアセットを作成します。

uGuiのTextとButtonを作成、TextをRebindingMessageと命名しActive状態をFalseにします。ButtonをRebindingButtonとします。

新規c#ファイル「RebindingInput.cs」を作成し、先ほどのGameObjectにコンポーネントとして追加します。コードは以下の通り。

Unity InputSystem キーコンフィグの実装1

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class RebindingInput : MonoBehaviour
{
    //PlayerInputコンポーネントがあるゲームオブジェクト
    [SerializeField]
    private PlayerInput _pInput;

    //リバインディング中のメッセージ表示テキスト。アクティブ状態の可否に使用。
    [SerializeField]
    private GameObject _rebindingMessage;
    //リバインディングを開始するボタン。アクティブ状態の可否に使用。
    [SerializeField]
    private GameObject _rebindingButton;
    //リバインディング開始ボタンのテキスト。キー名を表示。
    [SerializeField]
    private Text _bindingName;

    //リバインディングしたいInputAction項目。今回はMap:PlayerのAction:Fireを使用しています。
    [SerializeField]
    private InputActionReference _action;
    //リバインディングしたいコントロールのインデックス
    private string rebindingIndex;

    private InputActionRebindingExtensions.RebindingOperation _rebindingOperation;
    public void Start()
    {
        //アクション(Fire)ボタンを押下するとデバッグにFireと表示
        _pInput.actions["Fire"].performed += _ => Debug.Log("Fire");

        //すでにリバインディングしたことがある場合はシーン読み込み時に変更。
        string rebinds = PlayerPrefs.GetString("rebindSample");

        if (!string.IsNullOrEmpty(rebinds))
        {
            //リバインディング状態をロード
            _pInput.actions.LoadBindingOverridesFromJson(rebinds);

            //バインディング名を取得
            int bindingIndex = _action.action.GetBindingIndexForControl(_action.action.controls[0]);
            _bindingName.text = InputControlPath.ToHumanReadableString(
                _action.action.bindings[bindingIndex].effectivePath,
                InputControlPath.HumanReadableStringOptions.OmitDevice);
        }


    }

    public void StartRebinding()
    {
        //ボタンを消し、代わりにリバインディング中のメッセージを表示
        _rebindingButton.SetActive(false);
        _rebindingMessage.SetActive(true);
        
        //ボタン制御中の表示
        //ボタンの誤作動を防ぐため、何も無いアクションマップに切り替え
        _pInput.SwitchCurrentActionMap("Select");

        //Fireボタンのリバインディング開始
        _rebindingOperation = _action.action.PerformInteractiveRebinding()
            .WithTargetBinding(_action.action.GetBindingIndexForControl(_action.action.controls[0]))
            .WithControlsExcluding("Mouse")
            .OnMatchWaitForAnother(0.1f)
            .OnComplete(operation => RebindComplete())
            .Start();
    }

    public void RebindComplete()
    {
        //fireアクションの1番目のコントロール(バインディングしたコントロール)のインデックスを取得
        int bindingIndex = _action.action.GetBindingIndexForControl(_action.action.controls[0]);

        //バインディングしたキーの名称を取得する
        _bindingName.text = InputControlPath.ToHumanReadableString(
            _action.action.bindings[bindingIndex].effectivePath,
            InputControlPath.HumanReadableStringOptions.OmitDevice);

        _rebindingOperation.Dispose();

        //画面を通常に戻す
        _rebindingButton.SetActive(true);
        _rebindingMessage.SetActive(false);

        //リバインディング時は空のアクションマップだったので通常のアクションマップに切り替え
        _pInput.SwitchCurrentActionMap("Player");

        //リバインディングしたキーを保存(シーン開始時に読み込むため)
        PlayerPrefs.SetString("rebindSample", _pInput.actions.SaveBindingOverridesAsJson());
    }
}


次にButtonを押した時、StartRebinding()を実行するようにします。

Unity InputSystem キーコンフィグの実装2

InputActionアセットのAction Mapsに新しいマップ「Select」を追加します。何もアクションが存在しないマップです。

Unity InputSystem キーコンフィグの実装5

実行するとボタンが一つあり、選択するとキー入力画面になり、何かキーを押すと、そのキーがボタンのテキストに表示されます。また、初期はマウスの右クリックでログが出力しますが、以後は設定したキーを押すとログを出力するように変化します。

Unity InputSystem キーコンフィグの実装3
Unity InputSystem キーコンフィグの実装4

では、コードを解説します。

セーブ&ロード

//リバインディングしたキーを保存(シーン開始時に読み込むため)
PlayerPrefs.SetString("rebindSample", _pInput.actions.SaveBindingOverridesAsJson());

//リバインディング状態をロード
string rebinds = PlayerPrefs.GetString("rebindSample");
_pInput.actions.LoadBindingOverridesFromJson(rebinds);

InputSystem Ver1.10以降に利用できる機能です。その時のバインディングの状態をJSON形式で出力、読み込みができます。

RebindingOperation

リバインディングの核となるクラスです。

    _rebindingOperation = _fireAction.action.PerformInteractiveRebinding()
        .OnComplete(operation => RebindComplete())
        .Start();

実際のリバインディングを実行している箇所。「RebindingOperation = 指定のアクション.PerformInteractiveRebinding」でバインディングしたい項目をセットし、.Start()で実行します。リバインディング終了後にOnCompleteの処理を施して終了します。

OnComplete後、RebindingOperation.actionでリバインディング後のアクションの取得が可能です。

この他にも、RebindingOperationには様々なメソッド項目があります。

リバインディング項目の設定

指定したコントロールに対してバインディングを実行します。上記コードだと以下の箇所です。

.WithTargetBinding(_action.action.GetBindingIndexForControl(_action.action.controls[0]))
Unity Input System キーコンフィグ

Fireアクションの有効になっているコントロールの一番最初をリバインディングします。action.controlsは、例えば、キーボードの値を変更しようと思った場合、Control Schemesを「Keyboard & Mouse」に設定しているMが0番、Right Triggerが1番になります。それ以外の項目は取得できないようになっています。

今回はコントロールを指定する方法で実現しましたが、以下のようなメソッドも用意されています。これらは複合指定可能です。

WithAction指定したアクションをリバインディングします。
WithBindingGroup指定したグループ(Control Schemes)をリバインディングします。
WithBindingMask指定したマスクをリバインディングします。
WithCancelingThrough指定したコントロールをリバインディングします。
//以下のコードは同じ意味です。
_rebindingOperation = _action.action.PerformInteractiveRebinding();

_rebindingOperation = new InputActionRebindingExtensions.RebindingOperation()
        .WithAction(_action);

指定例

var rebind = new RebindingOperation()
    .WithAction(_action)
    .WithBindingGroup("Gamepad")
    .WithCancelingThrough("<Keyboard>/escape");

rebind.Start();

選択できないキーやデバイスを設定:WithControlsExcluding

WithControlsExcludingは、リバインディングできないデバイスやキーを設定できます。

.WithControlsExcluding("<Pointer>/position") 
.WithControlsExcluding("Mouse") 

特定のデバイスに設定:WithControlsHavingToMatchPath

WithControlsHavingToMatchPathは、リバインディングできるデバイスやキーを固定することができます。以下はゲームパッド以外のリバインディングを受け付けなくなります。

.WithControlsHavingToMatchPath("<Gamepad>");

Rebind Action UIコンポーネントを利用する

Input Systemのサンプル例にRebindingの実装を行っているサンプルがあります。各UI一つ一つにリバインドを設定できるコンポーネントになっており、手軽に利用できます。セーブできないので拡張する必要がありますが。

Package ManagerのInput Systemからsampleをクリックし、Rebinding UIをInstallします。

Unity Input System キーコンフィグ2

ボタンなど、一つ一つのリバインドしたいUIにコンポーネントを追加します。

Unity Input System キーコンフィグ3

Binding

Actionは、リバインドしたいInput Actionアセット内のアクションをセットします。

Bindingは、Actionでセットしたアクションに設定したコントロールが表示されるので、リバインドで上書きしても良い項目を選択します。

Display Optionはバインディング中にUIに表示したい項目です。

UI

Action Labelは、アクション名を表示します。

Binding Textは、Display Optionsで指定した項目を表示します。

Rebind Overlayは、リバインド中にアクティブにするゲームオブジェクトです。

Rebind Textは、リバインドしたキーを表示します。

関連リンク

参考 【Unity】Input Systemの紹介と解説 トップページゲーム開発65535 Ver2 参考 【Unity】Input Systemの紹介ゲーム開発65535 Ver2 参考 【Unity】Input Systemの基本的な使い方ゲーム開発65535 Ver2

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です