Input.GetKey(KeyCode.Space)でジャンプを書いたら、押している間ずっとジャンプが連打される。直したと思ったら、今度はInput Systemパッケージを入れた途端にInput.GetKeyが例外を吐いて止まる——入力処理は「最初に書くコード」なのに、つまずきポイントが意外と多い場所です。
この記事では、Unityに古くからある標準の Input Manager(Inputクラス)を使った入力処理を教科書的に整理します。先に位置づけをはっきりさせておくと、これは 「古いプロジェクトや教材のコードを読み、動かし、いずれ移行するため」のガイド です。いま新規プロジェクトを始めるなら、入口は New Input System入門 をおすすめします。とはいえ世の中のチュートリアルや既存資産の大半は旧Inputで書かれているので、これを読めることは今も必須スキルです。
この記事でわかること
- Unityに2つある入力システムの関係と、この記事の守備範囲
GetKeyDown/GetKey/GetKeyUpの正確な使い分け(「瞬間」と「間」)- 仮想軸(Virtual Axes)がある理由と
GetAxis/GetAxisRawの違い- マウス入力の取得方法
- 新Input Systemへ移行すべき判断基準
Unityには入力システムが2つある
最初に全体像です。Unityの入力には 2つの仕組みが併存 しています。

- Input Manager(旧・標準):
Input.GetKey(...)のようにUpdate内で毎フレーム問い合わせる(ポーリング型)。追加インストール不要で、1行から書き始められる - Input System(新・パッケージ): 「ジャンプ」「移動」というアクションを定義し、イベントで受け取る。キーコンフィグや複数デバイス対応に強い(New Input System入門 参照)
この記事は前者、Input Manager の教科書です。学習コストが低く、プロトタイプや小規模ゲームでは今でも現役の選択肢です。
補足(定番のハマりポイント): Input Systemパッケージをインストールすると、切り替え確認のダイアログを経て Active Input Handling が「Input System Package (New)」になり、旧
InputクラスがInvalidOperationExceptionを投げるようになります。両方使いたい場合は「Edit > Project Settings > Player > Other Settings > Active Input Handling」を Both に変更してください。「昨日まで動いていた入力が突然例外を吐く」ようになったら、まずここを疑いましょう。
Input Managerの基本:仮想軸という考え方
Input Managerの設定は「Edit > Project Settings > Input Manager」で確認できます。ここにはHorizontal、Vertical、Jump、Fire1といった 仮想軸(Virtual Axes) が予め定義されています。
なぜキーを直接読まず、わ ざわざ「軸」を挟むのか。コードを特定のキーから切り離すためです。

例えばHorizontal軸には、a/dキー、左右の矢印キー、そしてゲームパッドのスティックがまとめて割り当てられています。コード側はInput.GetAxis("Horizontal")と書くだけで、どの入力源から来たかを気にせず「左右の入力」として受け取れます。キーボード縛りのコードを書いてしまってから「パッド対応して」と言われて全書き換え——という事故を、この抽象化が防いでくれます。
キーボード入力の取得
キーボード入力はInputクラスの3つのメソッドで取得します。重要なのは「瞬間」と「間」の区別です。

| メソッド | 反応するタイミング | 主な用途 |
|---|---|---|
Input.GetKeyDown(KeyCode) | 押された 瞬間 の1フレームだけ | ジャンプ、射撃、決定など単発アクション |
Input.GetKey(KeyCode) | 押されている 間 ずっと | 溜め、ダッシュ、押しっぱなしの移動 |
Input.GetKeyUp(KeyCode) | 離された 瞬間 の1フレームだけ | 溜め撃ちの解放、長押しの終了 |
冒頭の「ジャンプが連打される」バグの正体はここです。GetKeyは押している間 毎フレーム trueを返すので、ジャンプに使うと1秒押しただけで数十回発動します。単発アクションは必ずGetKeyDownです。
KeyCodeはキーを定義した列挙型です(例: KeyCode.Space、KeyCode.W、KeyCode.Return)。
using UnityEngine;
public class KeyboardInputExample : MonoBehaviour
{
void Update()
{
// スペースキーが押された瞬間にジャンプ(1回だけ)
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("ジャンプ!");
}
// Rキーが押されている間、リロード中
if (Input.GetKey(KeyCode.R))
{
Debug.Log("リロード中...");
}
// Escapeキーが離された瞬間にポーズメニューを閉じる
if (Input.GetKeyUp(KeyCode.Escape))
{
Debug.Log("ポーズメニューを閉じる");
}
}
}
tips: 入力の検知は必ず
Updateで行います。FixedUpdateは毎フレーム呼ばれるとは限らないため、GetKeyDownのような「1フレームだけtrue」の入力を取りこぼすことがあります。詳しくは UpdateとFixedUpdateの記事 を参照してください。
仮想軸による入力取得
移動のような「方向と強さ」を持つ入力は、仮想軸で受け取ります。似た顔の2つのメソッドがあり、入力値の変化の仕方 が違います。

Input.GetAxis(string): -1.0〜1.0の値を スムーズに変化させて 返す。キーボードでも内部で補間がかかり、押した瞬間に0→1へなだらかに立ち上がる。慣性のある滑らかな移動向きInput.GetAxisRaw(string): 補間なしで 即座に -1、0、1を返す。押した瞬間からフルスピードで動く、キ ビキビした2Dアクション向き
なお、ゲームパッドのスティックの場合はどちらも倒し具合に応じた中間値(0.3や0.7など)が返ります。補間の有無が効くのは主にキーボード入力です。
using UnityEngine;
public class AxisInputExample : MonoBehaviour
{
public float speed = 10f;
void Update()
{
// "Horizontal"軸(A/Dキー、矢印キー、パッドのスティック)の値を取得
float horizontalInput = Input.GetAxis("Horizontal");
// 取得した入力値を使って左右に移動
transform.Translate(Vector3.right * horizontalInput * speed * Time.deltaTime);
}
}
「操作がもっさりする」と感じたらGetAxisRawに、「動き出しが唐突すぎる」と感じたらGetAxisに——と、手触りで選び分けるのが実務的です。
マウス入力の取得
マウスのクリックと位置もInputクラスで取得できます。
Input.GetMouseButtonDown(int button): ボタンが押された瞬間。0が左、1が右、2が中ボタンInput.GetMouseButton(int button): ボタンが押されている間Input.GetMouseButtonUp(int button): ボタンが離された瞬間Input.mousePosition: カーソルの スクリーン座標(ピクセル単位・左下原点)をVector3で返す。Z座標は常に0
using UnityEngine;
public class MouseInputExample : MonoBehaviour
{
void Update()
{
// 左クリックされたら
if (Input.GetMouseButtonDown(0))
{
// マウスのスクリーン座標を取得
Vector3 mousePos = Input.mousePosition;
Debug.Log("左クリック! 座標: " + mousePos);
}
}
}
mousePositionは画面上のピクセル座標なので、3D空間の「クリックした先のオブジェクト」を知りたい場合は、この座標からRayを飛ばします。この定番パターンは Physics.Raycastの記事 で詳しく解説しています。
実践:古い2D移動+ジャンプのコードを読んで動かす
仕上げに、古い教材で最もよく見かける「2D移動+ジャンプ」の完成形を、シリーズの方針( 入力はUpdateで読む・物理への適用はFixedUpdateで行う )どおりに組みます。この形が読めれば、世の中の旧Inputのコードはほぼ読めます。

// ファイル名: LegacyPlayerMove.cs — 旧Input APIの定番形
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class LegacyPlayerMove : MonoBehaviour
{
public float moveSpeed = 6f;
public float jumpForce = 12f;
private Rigidbody2D rb;
private float moveInput;
private bool jumpPressed;
void Awake() { rb = GetComponent<Rigidbody2D>(); }
void Update()
{
// 入力はUpdateで読む(GetButtonDownの「1フレームだけtrue」を取りこぼさない)
moveInput = Input.GetAxisRaw("Horizontal");
if (Input.GetButtonDown("Jump")) jumpPressed = true; // フラグに貯める
}
void FixedUpdate()
{
// 物理への適用はFixedUpdateで
rb.linearVelocity = new Vector2(moveInput * moveSpeed, rb.linearVelocity.y);
if (jumpPressed)
{
jumpPressed = false; // 使ったら必ず消す(貯めっぱなしだと着地後に勝手に跳ぶ)
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
}
補足: 古いコードでは
rb.velocityと書かれていますが、Unity 6ではrb.linearVelocityに改名されています(新旧API読み替えガイド 参照)。また、ジャンプをFixedUpdateで直接GetButtonDownすると取りこぼすため、 Updateで読んでフラグに貯め、FixedUpdateで消費する のがこの形の肝です。
もう1つ、読むときの重要ポイントがあります。"Horizontal"や"Jump"という文字列は、 そのプロジェクトのProject Settings > Input Managerの設定名 に依存しています。設定側で軸を消したりリネームしたりすると、コードは正しくてもArgumentException: Input Axis Horizontal is not setup.のような実行時エラーになります。「コードだけコピーしたのに動かない」ときは、まずここを見ましょう。
新Input Systemへの読み替え対照表
このコードをいつか新Input Systemへ移行するときは、次の対応で読み替えます(実装手順は New Input System入門 へ)。
| 旧Input Manager | 新Input System |
|---|---|
Input.GetAxisRaw("Horizontal") | Moveアクション(Vector2)のReadValue<Vector2>().x |
Input.GetButtonDown("Jump") | Jumpアクションのperformedコールバック(またはWasPressedThisFrame()) |
| 定義場所: Project Settings > Input Manager | 定義場所: Input Actionsアセット |
| デバイス追加=設定の書き足し | デバイス追加=Bindingの追加(コード変更なし) |
仕上げに、ジャンプを短くタタッと連打してみてください。1回も取りこぼさなければ、「Updateで読んでフラグに貯める」がきちんと働いています。そしてArgumentExceptionが出たときに、コードではなくProject Settingsの設定名へ真っ先に目が行くようになっていれば——世の中の旧Inputコードは、もうあなたの読める言語です。
注意点:Input Managerの引き際
Input Managerはシンプルさが武器ですが、プロジェクトが育つと限界が見えてきます。
- キーコンフィグが作りにくい: 仮想軸の割り当ては実行時に変更できないため、「キー設定画面」を自作するのはかなり大変です
- 複数デバイスの本格対応がつらい: キーボード+パッド+タッチを1つのコードで綺麗に扱うには、条件分岐が増え続けます
- 入力ロジックが散らばる:
Updateのポーリングは手軽な反面、入力の定義がコード中に埋まっていきます
こうした要件が出てきたら、イベントベースの 新Input System への移行を検討します。特にキーコンフィグは、新Input Systemな ら公式のリバインドAPIで実装できます(キーコンフィグ実装ガイド 参照)。
判断基準は1行です。 「プレイヤーにキー割り当てを変えさせたいか、複数デバイスを本気で対応するか」 ——どちらかがYesになった時が、新Input Systemへの移行タイミングです。逆に言えば、固定キーのPC向け小規模ゲームやプロトタイプなら、Input Managerで最後まで走り切っても何も問題ありません。
おまけ:先に知っておくと良いこと
基本の入力が書けるようになったら、次はこのあたりが視野に入ってきます。
- 入力とポーズの関係:
Time.timeScale = 0のポーズ中でも 入力は止まりません。だからこそポーズ解除の操作を受け付けられます。仕組みは ポーズ実装ガイド で整理しています。 - UIクリックとの衝突: ボタンの上でクリックしたのにゲーム内の射撃も発動してしまう——という場合は、
EventSystem.current.IsPointerOverGameObject()でUI上のポインタを判定して除外するのが定番です。 - モバイルのタッチ入力:
Input.GetMouseButtonDown(0)はタッチでも動作しますが、マルチタッチ(ピンチ操作など)が必要ならInput.touches、本格対応なら新Input Systemの出番です。
まとめ
入力処理は、プレイヤーとゲーム世界を繋ぐ最初のインターフェースです。
- Unityには 旧Input Managerと新Input Systemの2つ がある。Input Systemパッケージ導入で旧
Inputが例外を吐いたら Active Input HandlingをBoth に。 GetKeyDownは瞬間、GetKeyは間、GetKeyUpは離した瞬間。単発アクションをGetKeyで書くと連打バグになる。- 仮想軸はコードをキーから切り離す仕組み。
GetAxisはスムーズ、GetAxisRawは即座——手触りで選ぶ。 - マウスは
GetMouseButtonDownとmousePosition。3DオブジェクトのクリックはmousePositionからのRaycastで。 - キーコンフィグか本格マルチデバイス対応が必要になったら、新Input Systemへ移行する。
まずはInput Managerでキャラクターを動かす気持ちよさを体験して、プロジェクトの要件が育ってきたら新Input Systemへ——それが、遠回りに見えて一番堅実なステップアップです。