【Unity】Unityでキーコンフィグを実装する - New Input SystemのInteractive Rebinding入門

作成: 2026-07-05最終更新: 2026-07-13

設定画面の「キー変更」ボタン、どう作る?New Input SystemのPerformInteractiveRebindingを使ったキーコンフィグ(リバインド)の実装を、Bindingの上書きの仕組みからUI連携、保存・復元まで順番に解説します。

オプション画面の「ジャンプ: Space [変更]」というあのボタン——キーコンフィグは、今どきのPCゲームではあって当たり前の機能です。そして「プレイヤーがキーを差し替えられる」ことこそ、New Input System を選ぶ最大の理由のひとつ。ところがいざ作ろうとすると、「押されたキーをどう待ち受ける?」「変更をどう保存する?」と手が止まりがちです。

この記事では、New Input Systemの PerformInteractiveRebinding() を使ったリバインド実装を、仕組み(Bindingの上書き)→ 基本実装 → UI連携 → 保存・復元の順で解説します。

キーキャップを差し替えるイメージ

この記事でわかること

  • リバインドの正体は「Bindingの上書き(override)」であること
  • PerformInteractiveRebinding()による「次の入力を待って差し替える」実装
  • 変更したキーの表示・変更待ち状態などUIとの連携
  • SaveBindingOverridesAsJsonによる保存と起動時の復元

Sponsored

仕組み:リバインド=Bindingの上書き

New Input Systemでは、「ジャンプ」というアクションと「Spaceキー」という Binding(割り当て) が分離されています。リバインドとは、このBindingを書き換えること——正確には、元の定義はそのままに、上書き(override)を被せることです。

Bindingの上書きの概念図。ジャンプアクションの元の割り当てSpaceの上に、overrideとして新しいキーEが被さり、元の定義は下に残っている

元の定義(Input Action Assetに保存されたSpace)は消えません。上書きシールを貼るようにoverridePathが優先されるだけなので、シールを剥がせばいつでもデフォルトに戻せます。この構造が、後述の「リセット機能」や「保存のしやすさ」に直結しています。

基本実装:PerformInteractiveRebinding

「変更ボタンを押す → 次に押されたキーを待つ → そのキーで上書きする」という一連の流れを、PerformInteractiveRebinding()が丸ごと引き受けてくれます。

リバインドの3ステップの図。1. 変更ボタンを押す、2. 入力待ち状態で次のキー入力を待ち受ける、3. 押されたキーで上書きが確定してUIに反映される
using UnityEngine;
using UnityEngine.InputSystem;

public class RebindController : MonoBehaviour
{
    [SerializeField] private InputActionReference jumpAction; // ジャンプのアクション

    private InputActionRebindingExtensions.RebindingOperation rebindOperation;

    public void StartRebind()
    {
        // 1. リバインド中に反応しないよう、対象アクションを無効化
        jumpAction.action.Disable();

        // 2. 「次の入力」を待ち受けて上書きする操作を開始
        rebindOperation = jumpAction.action.PerformInteractiveRebinding()
            .WithControlsExcluding("Mouse")          // マウス操作は候補から除外
            .WithCancelingThrough("<Keyboard>/escape") // Escapeでキャンセル
            .OnComplete(operation => FinishRebind())  // 確定時
            .OnCancel(operation => FinishRebind())    // キャンセル時
            .Start();
    }

    private void FinishRebind()
    {
        // 3. 後片付け(Disposeを忘れるとメモリリークの原因に)
        rebindOperation.Dispose();
        jumpAction.action.Enable();
    }
}

押さえるべきポイントは3つです。

  • 開始前にDisable(): 有効なまま始めると、リバインド中の入力にアクション自体が反応してしまいます
  • WithCancelingThrough: 「やっぱりやめた」用のキャンセルキーを必ず用意します
  • 完了・キャンセルどちらでもDispose(): リバインド操作は使い捨てのオブジェクトです。後片付けとEnableを共通の後処理にまとめると漏れません

注意: アクションに複数のBindingがある場合(例:ジャンプに「Space」と「ゲームパッドの南ボタン」の2つ)、無指定のPerformInteractiveRebinding()では 意図しない側のBindingを書き換えてしまう ことがあります。実戦ではPerformInteractiveRebinding(bindingIndex)のように どのBindingを変更するかを必ず指定 しましょう。WASDのようなコンポジットBindingでは必須です(おまけ参照)。

Sponsored

UIと連携する

実際の設定画面では、「現在のキー表示」と「変更待ち状態の表示」が必要です。現在の割り当てはGetBindingDisplayString()で人間向けの表記(「Space」「Left Button」など)が取れます。

using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;

public class RebindButtonUI : MonoBehaviour
{
    [SerializeField] private InputActionReference jumpAction;
    [SerializeField] private TextMeshProUGUI keyLabel; // ボタン上のキー名表示

    private bool isRebinding; // 二重開始を防ぐフラグ

    private void Start()
    {
        RefreshLabel();
    }

    public void RefreshLabel()
    {
        // 現在の割り当てを「Space」のような表示用文字列で取得
        keyLabel.text = jumpAction.action.GetBindingDisplayString();
    }

    public void OnClickRebind()
    {
        // ボタン連打で2つ同時にリバインドを始めない
        if (isRebinding) return;
        isRebinding = true;

        keyLabel.text = "..."; // 変更待ち状態の表示

        jumpAction.action.Disable();
        jumpAction.action.PerformInteractiveRebinding()
            .WithControlsExcluding("Mouse")
            .WithCancelingThrough("<Keyboard>/escape")
            .OnComplete(op => { op.Dispose(); jumpAction.action.Enable(); isRebinding = false; RefreshLabel(); })
            .OnCancel(op => { op.Dispose(); jumpAction.action.Enable(); isRebinding = false; RefreshLabel(); })
            .Start();
    }
}

ボタンのOnClickOnClickRebindを繋げば、「クリック → 表示が ... に変わる → キーを押すと新しいキー名になる」という定番の挙動が完成します。

保存と復元

上書きはあくまで実行中のメモリ上の状態なので、ゲームを終了すると消えます。保存にはSaveBindingOverridesAsJson()を使います。上書き情報だけがJSON文字列になるので、PlayerPrefs にそのまま入れられます。

using UnityEngine;
using UnityEngine.InputSystem;

public class RebindSaveLoad : MonoBehaviour
{
    [SerializeField] private InputActionAsset actions; // Input Action Asset全体

    private const string SaveKey = "rebinds";

    // 設定画面を閉じるときなどに呼ぶ
    public void SaveRebinds()
    {
        string json = actions.SaveBindingOverridesAsJson();
        PlayerPrefs.SetString(SaveKey, json);
    }

    // ゲーム起動時に呼ぶ
    private void Awake()
    {
        string json = PlayerPrefs.GetString(SaveKey, string.Empty);
        if (!string.IsNullOrEmpty(json))
        {
            actions.LoadBindingOverridesFromJson(json);
        }
    }

    // 「デフォルトに戻す」ボタン用
    public void ResetRebinds()
    {
        actions.RemoveAllBindingOverrides();
        PlayerPrefs.DeleteKey(SaveKey);
    }
}

「上書きだけを保存する」設計のおかげで、保存・復元・リセットがそれぞれ数行で済みます。冒頭の「上書きシール」のイメージそのままです。

なお、アップデートでアクションやBindingの構成を変えたあとに古い保存データを読み込むと、期待と違う割り当てになることがあります。凝った移行処理を作り込むより、 「デフォルトに戻す」ボタンを設定画面に置いておく のが、いちばんシンプルで確実な保険になります。

Sponsored

おまけ:先に知っておくと良いこと

基本のリバインドが動いたら、次はこのあたりが課題になってきます。

  • WASD(コンポジット)のリバインド: 移動のようなWASD4方向の割り当ては「コンポジットBinding」で、上下左右それぞれの部分Bindingを個別にリバインドします。PerformInteractiveRebinding(bindingIndex)のように対象インデックスの指定が必要です。
  • 重複割り当てのチェック: 「ジャンプも攻撃もEキー」を許すかはゲーム次第です。許さない場合はOnComplete時に他アクションのBindingと比較し、重複していたら上書きを取り消す処理を足します。
  • ゲームパッドとの共存: キーボード用とゲームパッド用のBindingは別々に存在します。リバインド候補を絞りたいときはWithControlsExcludingや、対象スキームの指定を活用しましょう。New Input Systemの基礎から確認したい場合は 入門記事 へ。

まとめ

キーコンフィグは、New Input Systemなら「仕組みに乗るだけ」で実装できます。

  • リバインドの正体は Bindingの上書き(override)。元の定義は残るので、いつでもデフォルトに戻せる。
  • PerformInteractiveRebinding() が「次の入力を待って差し替える」流れを丸ごと担当。開始前のDisable()、キャンセルキー、Dispose()の3点セットを忘れずに。
  • 現在のキー表示は GetBindingDisplayString()。変更待ちは表示を差し替えるだけで実現できる。
  • 保存は SaveBindingOverridesAsJson + PlayerPrefs、復元は起動時にLoadBindingOverridesFromJson、リセットはRemoveAllBindingOverrides

「キー変更できて当たり前」の時代に、この実装がそのまま自分のゲームの設定画面になります。ぜひ組み込んでみてください。