【Unity2D】プレイヤーをジャンプさせる方法|(コード全文・解説付き)

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

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

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

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

といったことはありませんか?
この記事では、ジャンプさせる実装法(解説付き)、二重ジャンプ防止対策も含めて
初心者向けにわかりやすく解説します!

Unityの移動処理には「AddForce・velocity・transform」の3種類の実装方法がありますが、
今回は重力を活かして自然なジャンプにしたいので、AddForceを使った実装方法を解説しています。
他の実装方法の解説、比較もしていますので、よければご参照ください!


① 今回の完成イメージ

  • Input System を使ってジャンプ操作をさせる
  • 地面にいる時だけジャンプ可能(空中連打で多段ジャンプしない)
  • Rigidbody2D を使用
  • 接地判定は BoxCast で足元をチェック

Input Systemでボタン操作を設定している前提で進めています。
Input Systemの導入がまだ出来ていない場合は、まずこちらの記事から読むとスムーズです👾
(※旧Input版の実装方法も後半で解説あり)


② 事前準備

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

⇩インスペクターの設定を以下のような感じにしておきます

プレイヤー側

  • Rigidbody2D
  • Collider2D(BoxCollider2Dなど)

床側

  • Collider2D(BoxCollider2D / TilemapCollider2Dなど)

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

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

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

    private bool _bJump;
    private Collider2D _col;         // 実寸取得用
    
    void Start()
    {
        _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("ジャンプ速度")]
    private float _jumpSpeed;
    
    [SerializeField, Header("接地判定用レイヤー(Floorなど)")]
    private LayerMask _groundMask;   // インスペクターでFloorを指定

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

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

✅ Tag判定でも同じことが出来ますが、今回はLayerMaskで進めています。
LayerMaskは「物理判定の対象を限定するための仕組み」で今回のような地面だけ判定するような接地判定に向いています。


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

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

Update(接地状態を更新)

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

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


_HitFloor (BoxCastで接地判定する)

Colliderが存在するか確認
if (_col == null) return;

ここでは
プレイヤーのColliderが取得できているかを確認しています。

もしColliderが存在しない状態で処理を続けると
エラーが発生してしまうため、Colliderが無い場合 処理を中断するという安全対策です。

プレイヤーの当たり判定サイズを取得
Bounds b = _col.bounds;

ここでは
**プレイヤーのコライダーの範囲(サイズ・位置)**を取得しています。

Boundsには次のような情報が入っています。

情報内容
centerコライダーの中心
minコライダーの一番下
sizeコライダーのサイズ

つまりプレイヤーの大きさ、プレイヤーの位置を取得しています。

接地判定の中心位置を決める
Vector2 center = new Vector2(b.center.x, b.min.y - 0.05f);

ここでは
地面を判定する位置を決めています。

ポイントはここです。
b.min.y

これは、プレイヤーコライダーの一番下の位置です。
さらに-0.05fをしている理由はプレイヤーの足元より少し下で判定するためです。

   プレイヤー
┌─────┐
│ │
│ │
└─────┘ ←ここがb.min.y □ ←この少し下で接地判定
────────── 地面

こうすることで
足元に地面があるかを正確に判定できます

判定する矩形サイズを決める
Vector2 size = new Vector2(b.size.x * 0.9f, 0.12f);

ここではBoxCastのサイズを設定しています。
b.size.x * 0.9f(横幅)で、プレイヤーの幅より少しだけ小さくしています。
理由は、壁に触れたときに地面と誤判定しないようにするためです。

0.12f(高さ)かなり薄くしています。
これは、足元のわずかな範囲だけを判定するためです。

BoxCastで地面をチェック
RaycastHit2D hit = Physics2D.BoxCast(
    center,
    size,
    0f,
    Vector2.down,
    0.05f,
    _groundMask
);

ここが この処理の一番重要な部分です。
BoxCastとは四角形を飛ばして当たり判定をチェックする機能です。

イメージ

プレイヤー

▼[ □ ] ←判定ボックス


地面

各引数の意味はこちら。

引数意味
center判定の中心
size判定の大きさ
0f回転なし
Vector2.down下方向に判定
0.05f飛ばす距離
_groundMask地面レイヤーだけ判定

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

方法用途
Raycast足元・視線判定
CircleCast丸いキャラ向き
BoxCast四角形2Dキャラの接地判定に最適
なぜジャンプ判定でBoxCastを使うのか?

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

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

Raycast(線)だと、


  |
|

 ̄ ̄ ̄ ̄

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

でも BoxCast なら:


███ ← 薄い箱
 ̄ ̄ ̄ ̄

足元全体をチェックできるので安定しやすくなります🚶

地面に当たったか確認
bool grounded = (hit.collider != null);

BoxCastが

  • 地面に当たった → colliderが存在
  • 当たってない → null

になります。
つまり hit.collider != nullは、地面に触れているかどうかを意味しています。


ジャンプ可能かどうかを設定
if (grounded)
{
    _bJump = false;
}
else
{
    _bJump = true;
}

bool grounded = (hit.collider != null);bool grounded = (hit.collider != null);

ここでは、

状態処理
地面にいるジャンプ可能
空中ジャンプ不可

という状態を設定しています。

この _bJump をジャンプ処理で使います。

_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 のとき(空中)は処理をスキップ。
  • ジャンプ処理にはいくつかの実装方法がありますが、AddForce(Rigidbodyに力を加える関数)を使う理由は物理挙動を活かして自然なジャンプにするためです。
    上方向(Y軸プラス方向)に対しジャンプの強さ(高さ)を図り、ForceMode2D.Impulseを引数で渡すことで、一瞬だけ強い力を加えることができます。
    こうすることで、初速を一気に与えて自然なジャンプ挙動になります。

AddForceは重力と組み合わさることで、
上昇→減速→落下の自然なカーブを描きます。
そのため、より気持ちのいいジャンプになります!
今回のようなアクションゲームならAddForceがおすすめです!

⬇️他にも、AddForce以外には以下のような方法があります。

方法特徴物理挙動主な用途
_rigid.AddForce力を加える◎(自然)ジャンプ・吹っ飛び
_rigid.velocity速度を直接指定○(やや物理)移動、定速移動
transform位置を直接変更✕(物理なし)UI・演出・単純移動

velocityでジャンプさせる方法(速度を直接指定)

速度を直接指定でき、瞬時に移動させることが出来るのが特徴です。

_rigid.velocity = new Vector2(_rigid.velocity.x, _jumpSpeed);

メリット・・・操作が安定する(毎回同じ動き)、細かい制御がしやすい横移動との相性が良い
デメリット・・・物理感は少し薄れる、慣性が消える(急に止まる)

向いている用途は、プレイヤーの左右移動、シンプルなジャンプ制御、アクションゲーム全般です。


transformでジャンプさせる方法(位置を直接変更)

Rigidbodyを使用せず、位置を直接変更する方法です。

transform.position += Vector3.up * 5f;

メリット・・・シンプルで分かりやすい、Rigidbody不要、軽い
デメリット・・・当たり判定が壊れやすい、物理エンジン無視、壁すり抜けなどが起きる

向いている用途は、UI、カメラ移動、背景スクロール演出効果などです。

⑤ Floor レイヤーの作成

「床」と判定するFloor レイヤーを追加します。

新しいレイヤーを作る

どのオブジェクトでもいいのでクリックし、「Inspector」ウィンドウを確認
「Layer」の右端にあるプルダウンをクリック → 一番下の 「Add Layer…」 を選びます。
 (インスペクターが Tags & Layers の設定画面に切り替わります。)

レイヤーの設定方法

その空欄に Floor と入力してください。
(大文字・小文字は区別されないですが、コードと統一した方が安全です)

レイヤーの追加方法

床オブジェクトに Floor レイヤーを割り当てる

  • Hierarchy 上で「床」となるオブジェクトを選択。
  • Inspector の Layer プルダウンから、先ほど作成した Floor を選びます。
Floor レイヤーを割り当てている様子

Ground MaskにFloorレイヤーを割り当てる

  • Playerオブジェクトを選択
  • Ground Maskに今作成した Floor を選びます。
Ground MaskにFloorレイヤーを割り当てている様子

ここまで設定したらジャンプ処理の完成です!


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

↓ジャンプが動かない、挙動が変な場合は以下を確認してみてください

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

  • 床オブジェクトのLayerMaskが設定されていない
    • ✅Layer:「Floor」を設定する
「Floor」を設定する方法
  • プレイヤー側の「床」と判定するレイヤー(_groundMask )の指定がされていない
    • ✅GroundMask:「Floor」を設定する
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;
}

まとめ

今回の処理は次の流れになっています。

① プレイヤーのコライダー情報を取得
② 足元の位置を計算
③ 小さい矩形を作る
④ BoxCastで下方向に判定
⑤ 地面に当たったか確認
⑥ ジャンプ可能か設定

この処理によって

  • 空中ジャンプ防止
  • 正確な接地判定

が実現できます!!

今回は、Unity2Dでのジャンプ実装方法を解説しました。

最後まで読んでいただきありがとうございました!

他にも、
「プレイヤーを追従させるカメラワークを作りたい」
「歩行やジャンプ時にアニメーションをつけたい」

という実装したい人は、こちらの記事もご興味あれば覗いてみてください👾


コメント

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