Unity 6でキャラクターを動かしてジャンプさせる ― Input SystemとRigidbody2Dの基本
はじめに
前回の記事では、transform.position を書き換えてPlayerを動かしました。この方法は簡単ですが、床に乗る、壁にぶつかる、ジャンプして落ちるといった動きは、自分で計算する必要があります。
今回は、動きを物理エンジン(Rigidbody2D)に任せる方法に切り替えます。左右の移動とジャンプを作り、「空中ではジャンプできない」ところまで仕上げます。
今回作るもの

- A / D キー(または矢印キー)で左右に動く
- スペースキーでジャンプする
- 地面に立っているときだけジャンプできる(空中ジャンプは不可)
準備
Input Systemの準備(Project-wide Actions の InputSystem_Actions、Active Input Handling)は前回の記事と同じです。まだの方は、前回の記事を先に確認してください。
① 地面(Ground)を作る
- Hierarchyで右クリック → 2D Object → Sprites → Square を作り、名前を
Groundにする - Position を (0, -3, 0)、Scale を (10, 1, 1) にする
- Add Component で Box Collider 2D を追加する
- Inspector右上の Layer → Add Layer で
Groundというレイヤーを作り、Groundに設定する
② Playerを作る
- Square を作り、名前を
Playerにする(Positionは (0, 0, 0)) - Rigidbody 2D を追加する(Body Type は Dynamic のまま)
- Box Collider 2D を追加する
- Rigidbody 2D の Constraints を開き、Freeze Rotation の Z にチェックを入れる(倒れて転がるのを防ぐ)
- Gravity Scale を 3 にする(落ち方が重くなり、ジャンプが操作しやすくなる)
③ 足元の目印(GroundCheck)を作る
- Player を右クリック → Create Empty で子オブジェクトを作り、名前を
GroundCheckにする - Position を (0, -0.5, 0) にする(標準のSquareは1×1なので、足元はちょうど -0.5。大きさを変えた場合は足元に合わせる)
Player自身は Ground レイヤーにしません(Defaultのままにします)。
スクリプトを書く
Player に PlayerController というスクリプトを追加し、次のように書きます。
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
[SerializeField] private float moveSpeed = 5.0f;
[SerializeField] private float jumpSpeed = 10.0f;
[SerializeField] private Transform groundCheck;
[SerializeField] private float groundCheckRadius = 0.1f;
[SerializeField] private LayerMask groundLayer;
private Rigidbody2D rb;
private InputAction moveAction;
private InputAction jumpAction;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
moveAction = InputSystem.actions.FindAction("Player/Move");
jumpAction = InputSystem.actions.FindAction("Player/Jump");
}
private void Update()
{
// 左右:横方向の速さだけ決める。縦方向は今の速さのまま(重力に任せる)
Vector2 moveInput = moveAction.ReadValue<Vector2>();
rb.linearVelocity = new Vector2(moveInput.x * moveSpeed, rb.linearVelocity.y);
// ジャンプ:押した瞬間 かつ 地面にいるとき
if (jumpAction.WasPressedThisFrame() && IsGrounded())
{
rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpSpeed);
}
}
private bool IsGrounded()
{
// 足元の小さな円がGroundレイヤーのColliderに触れているか
return Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer) != null;
}
}
Inspector で次のように設定します。
| 項目 | 設定 |
|---|---|
| Move Speed | 5 |
| Jump Speed | 10 |
| Ground Check | Playerの子の GroundCheck をドラッグ |
| Ground Check Radius | 0.1 |
| Ground Layer | Ground |
再生して、A / D(または矢印キー)で動き、スペースキーでジャンプできれば成功です。
コードを読む
入力の取り方(前回と同じ)
InputSystem.actions.FindAction("Player/Move") で、Project-wide Actions の Player マップにある Move を取得します。Jump も同じ形で取ります。毎フレーム探さず、Start で1回だけ探して保存しておきます。
rb.linearVelocity:速さを直接決める
Rigidbody2D の速さ(1秒あたりに進む距離)です。横方向は入力から決め、縦方向は rb.linearVelocity.y(今の値)をそのまま残しています。こうすると、落下や着地は物理エンジンに任せたまま、左右だけ操作できます。
古い記事で rb.velocity と書かれていたら、Unity 6では rb.linearVelocity に読み替えます。
WasPressedThisFrame():押した瞬間だけ true
スペースキーを押したそのフレームだけ true になります。押しっぱなしでも1回しか反応しないので、ジャンプの入力に向いています。
Physics2D.OverlapCircle:足元に地面があるか
足元(GroundCheck)に小さな円を置き、Ground レイヤーのColliderに触れているかを調べます。触れていればそのColliderが返り、何もなければ null が返ります。!= null で「地面にいるか」の true / false にしています。
数字で見る
Gravity Scale 3、Jump Speed 10 の場合の目安です(Physics 2D の重力は標準で 9.81)。
| 項目 | 計算 | 目安 |
|---|---|---|
| 重力 | 9.81 × 3 | 約 29.4 |
| ジャンプの高さ | 10 × 10 ÷ (2 × 29.4) | 約 1.7(Playerの高さの約1.7倍) |
| 空中にいる時間 | 2 × 10 ÷ 29.4 | 約 0.68 秒 |
| 横の移動 | Move Speed 5 | 1秒で 5 進む |
Jump Speed や Gravity Scale を変えて、高さと時間がどう変わるか試してみましょう。
よくあるつまずき
| 症状 | 原因と直し方 |
|---|---|
| 何も動かない / NullReferenceException | FindAction の名前が違う(Player/Move、Player/Jump)か、Project-wide Actions が未設定。前回の記事の確認手順を見直す |
| ジャンプできない | Ground Layer が未設定、Ground Check が未割り当て、地面のレイヤーが Ground になっていない |
| 空中で何度でもジャンプできる | Player自身が Ground レイヤーになっている(自分のColliderに触れて、常に「地面にいる」になる) |
| Playerが倒れて転がる | Rigidbody 2D の Freeze Rotation Z にチェックが入っていない |
| 壁に押し付けると張り付いて落ちない | 壁との摩擦が原因。Physics Material 2D を作って Friction を 0 にし、PlayerのColliderに設定する |
| ジャンプが高すぎる / ふわふわする | Jump Speed を下げる、または Gravity Scale を上げる |
もう一歩
物理の処理は FixedUpdate に書くのが本来の形です。ただし、ボタンを押した瞬間の入力は Update で受け取らないと取り逃すことがあります。慣れてきたら、Update で「ジャンプを押した」という印(bool)だけ保存し、FixedUpdate で速さに反映する書き方にも挑戦してみましょう。
まとめ
- 動きを物理に任せるときは、
Rigidbody2DのlinearVelocityを使う - 横は入力から決め、縦は今の値を残す
- ジャンプは
WasPressedThisFrame()と接地判定の組み合わせで作る - 接地判定は、足元の円(
OverlapCircle)とレイヤーで行う
次回は、このPlayerを含むゲームを、Build Profilesを使ってWebGLやAndroidに出力します。










ディスカッション
コメント一覧
まだ、コメントがありません