記事の目的
前回、音量画面の実装を行いました。
前回記事 ⇒ #12_音量画面の設定
次はオプションからキー設定を変更できるようにしたいと考えていましたが、その前にキーボードでもコントローラーでも入力を受け付けるようにしてみたいと思います。
新InputSystem
複数デバイスの入力設定にはInputSystemとやらが有効なようです。
(前回はGPT-5しか使えず少しやりづらかったですが、いつの間にかGPT-4oが復活していましたので再びそちらを使っていきます。)
ChatGPTの回答(クリックで展開)
🎮 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がどういう意味を持っているか分からないので聞いていきます。
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.name
→w
やupArrow
などが表示される
✅ まとめ:ctx の本質
特性 | 内容 |
---|---|
イベント情報をまとめた構造体 | どのアクションが、どんな入力で、どのタイミングで発動したかを教えてくれる |
ReadValue<T>() が最重要 | 実際に入力された値を取得するためのメイン手段 |
特に重要なのは3つ | ReadValue<T>() / performed / canceled |
ctxには色々な情報が詰まっていてそれを取り出して操作をしたり、確認を行うというイメージでしょうか?
不要かと思いましたが、あって困るものでもなさそうです。
おわりに
次回はキー設定の変更をプレイヤー側でできるようにしていきます。
◇ 関連記事
オプション画面の実装はこちら