【Unity2D】ジャンプ処理を実装する方法

Unity2D実装解説(テクニック)

こんにちは!夜の街2Dアクションゲームを制作中の怪獣です🦖

Unity2Dでプレイヤーをジャンプさせたいけど、

  • ジャンプのさせ方が分からない
  • ジャンプが高くなりすぎる
  • 連続ジャンプしてしまう
  • 地面判定がうまくいかない

といった悩みはありませんか?
この記事では、Rigidbody2Dを使ったジャンプ実装方法を、
初心者向けにわかりやすく解説します!


①今回の完成イメージ

  • スペースキー(または Input System のJump)でジャンプ
  • 地面にいる時だけジャンプ可能(空中連打で多段ジャンプしない)
  • Rigidbody2D を使用
  • 接地判定は BoxCast で足元をチェック

②事前準備

プレイヤー、プレイヤーが立てる床のオブジェクトを用意しておきます。

プレイヤー側

  • Rigidbody2D
  • Collider2D(BoxCollider2Dなど)

床側

  • Collider2D(BoxCollider2D / TilemapCollider2Dなど)
  • 床を「Ground用のLayer(例:Floor)」に設定

※今回の判定は Tagではなく LayerMask を使います。
「Floorレイヤーのものだけ地面扱い」になるので、誤判定が減ります。


③ジャンプ処理の基本コード

Input System の Jump を呼ぶ前提で _OnJump() を用意しています。
旧Input(Input.GetKeyDown)版も後半で紹介します。

public class Player : MonoBehaviour
{   
    [SerializeField, Header("ジャンプ速度")]
    private float _jumpSpeed;
    
    [SerializeField, Header("接地判定用レイヤー(Floorなど)")]
    private LayerMask _groundMask;   // インスペクターでFloorを指定

    private Rigidbody2D _rigid;
    private bool _bJump;
    private Collider2D _col;         // 実寸取得用
    
    void Start()
    {
        _rigid = GetComponent<Rigidbody2D>();
        _col = GetComponent<Collider2D>();
        _bJump = false;
    }
    
    void Update()
    {
        _HitFloor();
    }
    
    // 今床に触れているか、空中状態か判定する
    private void _HitFloor()
    {
        // もしプレイヤーのColliderが存在しなければ処理しない
        if (_col == null) return;

        // 接地判定のためのBoxCast(四角形の当たり判定を下に飛ばす)を準備する

        // プレイヤーのコライダーの範囲を取得
        Bounds b = _col.bounds;
        // 判定を出す位置(プレイヤーの足元より少し下に設定)
        Vector2 center = new Vector2(b.center.x, b.min.y - 0.05f);
        // 判定の大きさ(横幅はキャラより少し小さめ、高さはごく薄い矩形)
        Vector2 size = new Vector2(b.size.x * 0.9f, 0.12f);

        // BoxCastを実行
        // ・center:判定の中心位置
        // ・size  :判定の大きさ
        // ・0f    :角度は回転なし
        // ・Vector2.down:真下に向けて判定
        // ・0.05f :判定を飛ばす長さ(わずかに下へ伸ばす)
        // ・_groundMask:Floorなど「地面」とするレイヤーにだけ反応させる
        RaycastHit2D hit = Physics2D.BoxCast(center, size, 0f, Vector2.down, 0.05f, _groundMask);

        // 当たり判定の情報取得
        bool grounded = (hit.collider != null);

        // 地面と触れたか確認
        if (grounded)
        {
            // 地面にいる → ジャンプ可能
            _bJump = false;
        }
        else
        {
            // 空中にいる → ジャンプ不可
            _bJump = true;
        }
    }
    // ジャンプ処理
    public void _OnJump(InputAction.CallbackContext context)
    {
        // 押下(performed)でなければ無視 / 空中なら無視
        if (!context.performed || _bJump) return;

        // Impulse:初速が早く徐々に減速、Force:初速が遅く、徐々に加速
        _rigid.AddForce(Vector2.up * _jumpSpeed, ForceMode2D.Impulse);

        // 連打での多段を防ぐために即座に空中扱い
        _bJump = true;
    }
}

④各処理の解説(初心者向け)

フィールド変数の追加


    [SerializeField, Header("接地判定用レイヤー(Floorなど)")]
    private LayerMask _groundMask;   // インスペクターでFloorを指定

    private Rigidbody2D _rigid;
    private bool _bJump;
    private Collider2D _col;         // 実寸取得用

_jumpSpeed:ジャンプの強さ(大きいほど高く跳ぶ)
_groundMask「床」と判定するレイヤーを指定します。(Floorなど)インスペクターで Floor レイヤーを選んでください。

✅ Tag判定よりLayer判定の方が、Tilemapや複数床でも管理しやすいです。


Start(必要コンポーネントを取得)

void Start()
{
    _rigid = GetComponent<Rigidbody2D>();
    _col   = GetComponent<Collider2D>();
    _bJump = false;
}
  • Collider2D (プレイヤー自身に付いている当たり判定情報)を取得して変数に保存。
  • _bJump は「今ジャンプ中かどうか」を管理するフラグです。初期値は false(ジャンプ可能)。

Update(接地状態を更新)

void Update()
{
    _HitFloor();       // 接地状態をチェック
}

Updateは毎フレーム呼び出されるUnityの共通機能です。
ここで _HitFloor() を呼び出して、接地中かどうかを更新します。


_HitFloor (BoxCastで接地判定する)

今床に触れているか、空中状態か判定するメソッドを作成します。
床に触れている場合はジャンプ可能、空中の場合はジャンプ不可能に制御します📝

   // 今床に触れているか、空中状態か判定する
    private void _HitFloor()
    {
        // もしプレイヤーのColliderが存在しなければ処理しない
        if (_col == null) return;

        // 接地判定のためのBoxCast(四角形の当たり判定を下に飛ばす)を準備する

        // プレイヤーのコライダーの範囲を取得
        Bounds b = _col.bounds;
        // 判定を出す位置(プレイヤーの足元より少し下に設定)
        Vector2 center = new Vector2(b.center.x, b.min.y - 0.05f);
        // 判定の大きさ(横幅はキャラより少し小さめ、高さはごく薄い矩形)
        Vector2 size = new Vector2(b.size.x * 0.9f, 0.12f);

        // BoxCastを実行
        // ・center:判定の中心位置
        // ・size  :判定の大きさ
        // ・0f    :角度は回転なし
        // ・Vector2.down:真下に向けて判定
        // ・0.05f :判定を飛ばす長さ(わずかに下へ伸ばす)
        // ・_groundMask:Floorなど「地面」とするレイヤーにだけ反応させる
        RaycastHit2D hit = Physics2D.BoxCast(center, size, 0f, Vector2.down, 0.05f, _groundMask);

        // 当たり判定の情報取得
        bool grounded = (hit.collider != null);

        // 地面と触れたか確認
        if (grounded)
        {
            // 地面にいる → ジャンプ可能
            _bJump = false;
        }
        else
        {
            // 空中にいる → ジャンプ不可
            _bJump = true;
        }
    }


BoxCastとは?

一言で言うと、「四角形を飛ばして、当たり判定を行う機能」です。

Unityにはいくつかの判定方法があります。

方法用途
Raycast足元・視線判定
CircleCast丸いキャラ向き
BoxCast四角形2Dキャラの接地判定に最適

なぜジャンプ判定でBoxCastを使うのか?

プレイヤーは四角いことが多いですよね。

  □ ← プレイヤー
 ̄ ̄ ̄ ̄ ← 床

Raycast(線)だと、

   |
|

 ̄ ̄ ̄ ̄

→ ちょっとズレると判定ミスします。

でも BoxCast なら:

 ███ ← 薄い箱

 ̄ ̄ ̄ ̄

足元全体をチェックできるので安定しやすいです。

  • BoxCast で足元に薄い箱を飛ばし、床と接触しているかを確認する。
  • BoxCastのサイズ調整
    横幅を *0.9f にしているのは、左右ギリギリを避けて誤判定を減らすため。
    縦の大きさを小さくして「足元の薄い判定」としています。
  • grounded = true → 接地中(ジャンプできる)
  • grounded = false → 空中(ジャンプ禁止)
    これで「空中で無限ジャンプ」を防止できます!

_OnJump (ジャンプ処理)

public void _OnJump(InputAction.CallbackContext context)
{
    // 入力が押された瞬間以外は無視 / 空中中は無視
    if (!context.performed || _bJump) return;

    // Rigidbodyに上方向の力を加える
    _rigid.AddForce(Vector2.up * _jumpSpeed, ForceMode2D.Impulse);

    // ジャンプ直後は空中扱いにして多段ジャンプを防ぐ
    _bJump = true;
}
  • context.performed … 入力が「押された瞬間」だけ反応します。
  • _bJumptrue のとき(空中)は処理をスキップ。
  • AddForceImpulseモード で使うことで、初速を一気に与えて自然なジャンプ挙動になります。

⑤ ジャンプが高すぎる/低すぎる時の調整ポイント

_jumpSpeed を調整

8 → 6、10 などに調整

Rigidbody2D の「Gravity Scale」

重力が軽いとフワフワ、高いと重くなります。


⑥ よくあるエラーと対処法

❌ 地面にいるのにジャンプできない

  • 床の Layer_groundMask に含まれていない
  • _groundMask が「Nothing」になっている
  • BoxCast の center / size / distance が小さすぎて床に届いていない

✅ 対処:床をFloorレイヤーに設定 → Playerの_groundMaskにFloorをチェック


❌ 空中で連続ジャンプできる(多段になってしまう)

  • _HitFloor() が呼ばれていない/判定が機能していない
  • ジャンプ後 _bJump = true; を入れていない

✅ 対処:_OnJump の最後で _bJump = true; を必ず入れる


❌ 斜面や段差で接地判定がガタつく

  • sizeが薄すぎる/小さすぎる
  • distanceが短すぎる

✅ 対処:size.y0.05f を少し増やす(例:0.08f、0.1f)

⑦(任意)旧Input版(Input.GetKeyDown)での書き方

Input Systemを使っていない場合は、Updateでこう書けばOKです🙆

if (Input.GetKeyDown(KeyCode.Space) && !_bJump)
{
    _rigid.AddForce(Vector2.up * _jumpSpeed, ForceMode2D.Impulse);
    _bJump = true;
}

今回は、Unity2Dでのジャンプ実装方法を解説しました。
最後まで読んでいただきありがとうございました。

コメント

タイトルとURLをコピーしました