Unity ゲーム開発 生成AI

Unity素人がAI活用で進める独学個人ゲーム開発 #13_InputSystem

本記事では、コントローラーの入力設定(新InputSystem)について紹介します。

記事の目的

前回、音量画面の実装を行いました。
前回記事 ⇒ #12_音量画面の設定

次はオプションからキー設定を変更できるようにしたいと考えていましたが、その前にキーボードでもコントローラーでも入力を受け付けるようにしてみたいと思います。

新InputSystem

複数デバイスの入力設定にはInputSystemとやらが有効なようです。

(前回はGPT-5しか使えず少しやりづらかったですが、いつの間にかGPT-4oが復活していましたので再びそちらを使っていきます。)

UnityでInputSystemを実装したいです。1から解説してください

ChatGPTの回答(クリックで展開)
もちろん、Unityの新しい Input System を一から丁寧に解説します。

🎮 Unity Input System とは?

Unityの 新Input System は、旧Input(Input.GetKey() など)よりも柔軟かつモダンな入力管理を可能にします。ゲームパッド、キーボード、マウス、タッチ、モバイルなど多様なデバイスを簡単に統合できます。

導入ステップ(Unity 2021以降推奨)
Step 1:Input System パッケージの導入

Unityメニュー → Window > Package Manager
検索バーで Input System を検索
Input System を選び、右下の Install をクリック
「旧Inputとの競合に関するダイアログ」が出たら 「新Input System」に切り替える を選択
Unityが再起動されます

Step 2:Input Actions アセットの作成

Project ウィンドウで右クリック → Create > Input Actions
名前は例:PlayerInputActions
ダブルクリックして設定画面を開く

Step 3:Action Mapとアクションの作成

設定画面で以下を追加します:

📦 Action Map:Player
⬆ Add Action Map → Player

🎮 Actions(プレイヤーの操作を定義)

Action名 ActionType ControlType 使用用途例
Move Value Vector2 左右・上下移動(WASDやアナログスティック)
Fire Button Button 弾発射など
Pause Button Button ポーズメニュー表示など

🎮 Bindings(どのキー/デバイスに割り当てるか)

Move → WASD、Gamepad left stick
Fire → Space、Gamepad button South
Pause → Esc、Startボタン

Step 4:C#クラスを自動生成

設定画面右上の「Generate C# Class」にチェック
Apply をクリック
PlayerInputActions.cs が生成されます

Step 5:プレイヤースクリプトで使用

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private PlayerInputActions inputActions;
    private Vector2 moveInput;

    void Awake()
    {
        inputActions = new PlayerInputActions();
        inputActions.Player.Move.performed += ctx => moveInput = ctx.ReadValue<Vector2>();
        inputActions.Player.Move.canceled += ctx => moveInput = Vector2.zero;

        inputActions.Player.Fire.performed += ctx => Fire();
    }

    void OnEnable()
    {
        inputActions.Enable();
    }

    void OnDisable()
    {
        inputActions.Disable();
    }

    void Update()
    {
        Vector3 movement = new Vector3(moveInput.x, moveInput.y, 0);
        transform.position += movement * Time.deltaTime * 5f;
    }

    void Fire()
    {
        Debug.Log("Fire!");
    }
}

Step 6:PlayerInputコンポーネントの設定(オプション)

プレイヤーオブジェクトに PlayerInput コンポーネントを追加
作成した PlayerInputActions.inputactions をアサイン

「Behavior」設定:

  • Send Messages: MonoBehaviourに OnMove() などの関数が必要
  • Invoke Unity Events: UnityEventでUIと連携可能
  • Invoke C# Events: スクリプトからイベントとして受け取る(おすすめ)

💡Tips

  • デバッグ:Input Debugger は Window > Analysis > Input Debugger で開ける
  • 複数デバイス切替対応:PlayerInputManager を使えば、複数人プレイも可能
  • UIナビゲーションとの統合:InputSystemUIInputModule をEventSystemに追加することで可能

🎓次にやるべきこと

  • 操作設定をオプション画面で変更可能にする
  • Input System を UI操作にも適用
  • Gamepad 対応の表示切替(例:アイコンを "A" に)

続きを見たい場合は、以下のトピックで掘り下げます:

  • PlayerInput vs InputSystem.onAnyButtonPress
  • マルチプレイヤーでの Input System の使い方
  • ゲームパッド検出と動的切替
  • UI操作の組み込み(Pause/Optionなど)

必要であれば、フォルダ構成やスクリプト全体のサンプルも作成します!続きを見たいトピックを教えてください。

①パッケージ導入

Window > Package MAnager > 検索で"InputSystem"

②Input Action設定

キーボードのWASDを設定するときは各Actionの+ボタンからADD up~を選択

それぞれBindingでTを押すと直接選択可能

一通り指示があったところを設定しました。

ここまで手動入力をしてきましたが最初からある程度の操作が設定されているInputActionを作る方法があるようです。
空のオブジェクト > Add Componet > Player Input > Create Actions > 任意の名前で保存

設定済みのものが出てきました。Pauseが無かったので追加しましたがこれを使っていきます。

③スクリプトを自動作成

Inspectorから"Generate C# Class"にチェック⇒Apply

このC#スクリプトの役割は
・ActionMap(何を操作するときに)
・Action(何の行動が)
・ActionProperties(例:何に対応するか)
を保存してあるというイメージ

InputAction.Player.move.performedのようなコードで呼び出せる模様(performedはこの入力がされたときに呼ばれるイベント)

④ここまでの入力スクリプトを変更する。

これまでGetKeyDownなどで設定していたスクリプトを全てInputSystemを使用したコードに変更する必要があります。(次新しく作るときは最初からInputSystemを使います……)
今あるスクリプトを書き換えてもらいます。

using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float padding = 0.5f; // 画面端との余白

    private Rigidbody2D rb;
    private float inputY;

    private float minY, maxY;

    void Start()
    {
        rb = GetComponent();
        CalculateVerticalLimits();
    }

    void Update()
    {
        inputY = Input.GetAxis("Vertical");
    }

    void FixedUpdate()
    {
        rb.velocity = new Vector2(0, inputY * moveSpeed);

        // Y位置を画面内に制限
        Vector2 pos = transform.position;
        pos.y = Mathf.Clamp(pos.y, minY, maxY);
        transform.position = pos;
    }

    void CalculateVerticalLimits()
    {
        Camera cam = Camera.main;
        float camHeight = cam.orthographicSize;
        float screenBottom = cam.transform.position.y - camHeight;
        float screenTop = cam.transform.position.y + camHeight;

        minY = screenBottom + padding;
        maxY = screenTop - padding;
    }
}

Playerの移動についてのスクリプトです。InputSystemを使って書き換えてください

ChatGPTの回答(クリックで展開)
ありがとうございます!
この PlayerMovement スクリプトを Unity の 新Input System に対応させて書き換えたバージョンを、丁寧にご提供します。

ゴール

項目 対応内容
🎯 入力 Input.GetAxis("Vertical") → InputAction.ReadValue<float>() に変更
🧩 システム TestInput.inputactions の Move アクション(型:Vector2)を使用(Y方向だけ使用)
🔧 クラス構造 TestInput を使って inputY を更新

🧩 修正後スクリプト(Input System 対応)

using UnityEngine;
using UnityEngine.InputSystem;

[RequireComponent(typeof(Rigidbody2D))]
public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float padding = 0.5f; // 画面端との余白

    private Rigidbody2D rb;
    private float inputY;

    private float minY, maxY;

    private TestInput inputActions;

    void Awake()
    {
        inputActions = new TestInput();

        // 入力されたVector2からY方向の値だけ抽出して使う
        inputActions.Player.Move.performed += ctx =>
        {
            Vector2 move = ctx.ReadValue<Vector2>();
            inputY = move.y;
        };

        inputActions.Player.Move.canceled += ctx =>
        {
            inputY = 0;
        };
    }

    void OnEnable()
    {
        inputActions.Enable();
    }

    void OnDisable()
    {
        inputActions.Disable();
    }

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        CalculateVerticalLimits();
    }

    void FixedUpdate()
    {
        rb.velocity = new Vector2(0, inputY * moveSpeed);

        // Y位置を画面内に制限
        Vector2 pos = transform.position;
        pos.y = Mathf.Clamp(pos.y, minY, maxY);
        transform.position = pos;
    }

    void CalculateVerticalLimits()
    {
        Camera cam = Camera.main;
        float camHeight = cam.orthographicSize;
        float screenBottom = cam.transform.position.y - camHeight;
        float screenTop = cam.transform.position.y + camHeight;

        minY = screenBottom + padding;
        maxY = screenTop - padding;
    }
}

試してみたらキーボードのW/Sでも、ゲームパッドのスティックでも自機を動かせるようになりました!
これ以外にも4つほどのスクリプトを修正し動かせるようになりました。

おまけ

ctxがどういう意味を持っているか分からないので聞いていきます。

ctxまわりについてもう少し詳しく解説してください

ChatGPTの回答(クリックで展開)
了解しました。
それでは inputActions.Player.Move.performed += ctx => { ... };ctx(コールバックコンテキスト)について、超詳細に解説していきます。

🎯 ctxとは何か?
ctx => { ... }

ここで ctx は、Unityの新Input Systemで使われる特別な構造体:

UnityEngine.InputSystem.InputAction.CallbackContext

のインスタンスです。

🧠 なにが入ってるの?

ctx には、そのアクションが「発動したときの情報」がすべて詰まっています。

プロパティ 説明
ctx.ReadValue<T>() 入力された値を取得(型指定:float, Vector2 など)
ctx.performed 今のイベントが performed か(bool)
ctx.started 開始された瞬間か
ctx.canceled キーを離したなど、入力が終了した瞬間か
ctx.action 発動したアクションそのもの
ctx.control どのキーやボタンが押されたか
ctx.interaction 長押しや連打など、特殊な操作に関する情報

実例解説:inputActions.Player.Move.performed += ctx => { ... }

処理の流れ:

ctx => {
    Vector2 move = ctx.ReadValue<Vector2>();
    inputY = move.y;
}
ステップ 解説
ctx Moveアクションが発動した時の情報を受け取る
ctx.ReadValue<Vector2>() Wキーやスティックの入力方向(例:(0, 1))を取得
move.y そのうちの「上下方向」だけを抽出
inputY = move.y; プレイヤーの移動に使う変数に代入

🧪 さらに詳しく:他のパターン

🎮 例1:ボタン入力(Fire)

inputActions.Player.Fire.performed += ctx => {
    if (ctx.performed) Fire();
};
  • ctx.performed はこのイベントが「実際に押されたかどうか」の真偽値
  • Fire() は自分で作った発射処理

🎮 例2:float入力(トリガーやアナログ)

float triggerValue = ctx.ReadValue<float>();
  • ゲームパッドのトリガーなど、押し込みの強さが 0〜1 の float 値で取れます

🎮 例3:どのキーかを調べる

Debug.Log("押されたキー:" + ctx.control.name);
  • ctx.control.namewupArrow などが表示される

まとめ:ctx の本質

特性 内容
イベント情報をまとめた構造体 どのアクションが、どんな入力で、どのタイミングで発動したかを教えてくれる
ReadValue<T>() が最重要 実際に入力された値を取得するためのメイン手段
特に重要なのは3つ ReadValue<T>() / performed / canceled

ctxには色々な情報が詰まっていてそれを取り出して操作をしたり、確認を行うというイメージでしょうか?
不要かと思いましたが、あって困るものでもなさそうです。

おわりに

次回はキー設定の変更をプレイヤー側でできるようにしていきます。

◇ 関連記事
オプション画面の実装はこちら

  • この記事を書いた人

たげお

ソロゲームもオンラインゲームも対戦ゲームもソシャゲも楽しむ雑食ゲーマー。特筆して好きなジャンルはRPG、FPS。最近は格ゲーにお熱。 思い出のゲームは『FF9』

-Unity, ゲーム開発, 生成AI
-, , , ,