【ジャンプ編】Unityで2Dアクションゲームの作り方を解説

2D横スクロールアクションゲーム

今回も引き続きプログラムを組んでいきます。ジャンプの操作をできるように、前回作成したPlayerControllerに処理を追加していきましょう。

この投稿にはアフィリエイトリンクが含まれている可能性があります。これらのリンクをクリックしてもクリックすることに対して費用はかかりませんが、アセットを購入すると私が手数料を受け取ることがあります。受け取るアフィリエイト手数料はこのサイトの運営や私の開発プロジェクトなどに役立てさせていただきます。

ジャンプ処理の作り方

早速、ジャンプさせる処理を作っていきます。

横スクロール2Dアクションゲームで有名なマリオでは、ジャンプのキーを押す時間で高さが変わりますよね。
解説では分かりやすいように高さは一定で作りますが、余力のある方はプログラムを改造してマリオのようなジャンプを作ってみると勉強になると思います。

ジャンプのプログラミング

前回同様、プログラムを作成しました。追加したプログラムは、13行目のjumpForce変数・17行目~20行目のジャンプの判定・25行目~28行目のジャンプの処理です。

一行一行解説しますので、理解することを大切にプログラミングしてください。

尚、解説済みの処理については説明を省きます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(CapsuleCollider2D))]

public class PlayerController : MonoBehaviour
{
    [SerializeField] private Rigidbody2D rb;

    [SerializeField] private int moveSpeed;
    [SerializeField] private int jumpForce;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && !(rb.velocity.y < -0.5f))
        {
            Jump();
        }

        rb.velocity = new Vector2(Input.GetAxis("Horizontal") * moveSpeed, rb.velocity.y);
    }

    void Jump()
    {
        rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
    }
}

13行目のjumpForce変数は、ジャンプ力を調節するために使用します。他クラスに公開せずにインスペクターから値を設定したいため、[SerializeField]をつけています。

17行目~20行目はジャンプの判定をしています。スペースキーが押された際かつ落下中ではない時に、Jump関数が呼び出されます。
rigidbody 2Dのyの値は、オブジェクトが落下しているとマイナスになります。よって、「!(rb.velocity.y < -0.5f)」という条件を加えることで、落下中はジャンブできないようになります。条件を0未満ではなく、-0.5未満に設定している理由は、移動中にベクトルが加わることがあり、判定にゆとりを持たせるためです。

25行目~28行目はジャンプの処理をしています。関数を使用しているのは、処理ごとに分けることでプログラムが見やすくなる上、使い回すこともできて便利だからです。考え方は、Unityのプレファブ機能に似ています。
AddForceは、Rigidbody2Dのクラスに含まれている関数で、その名の通り力を加えます。Vector2.upはVector2(0, 1)と同じ意味ですので、y軸の正の方向へjumpForceを掛けてジャンプ力を調節しています。
Rigidbody2DのAddForce関数では、ForceImpulseの二種類の力を加える方法を利用できます。ForceMode2D.Forceを引数に与えると継続的に、ForceMode2D.Impulseを引数に与えると瞬間的に力を加えます。(省略するとForceになります)ジャンプ処理は、スペースキーを押した後、瞬間的に力を加えたいので、Impulseにしました。

以上でジャンプする処理のプログラムは完成です。

インスペクターの設定

インスペクターから、Jump Forceの値を設定します。好みで構いませんが、「7」に設定しました。

インスペクターでJump Forceの値を設定

「Overrides > Apply All」をクリックして、元のプレファブに変更を反映させます。

プレファブ元に変更を反映

以上で、インスペクターの設定は完了です。

ジャンプの動作確認

それでは動作確認してみましょう。プレイボタンをクリックしてください。

スペースキーを押した時にジャンプすれば、正常に動作しています。

ジャンプの動作確認

しかし問題が発生しました。それは二段ジャンプどころか無限にジャンプできてしまうことです。

ジャンプする際の条件を追加して、一回のみジャンプできるようにしましょう。

二段ジャンプの禁止方法

二段ジャンプを禁止する方法は、bool型の変数を用意して、ジャンプ時にtrue・着地時にfalseにする方法や、下が地面かどうかをRayCastで監視する方法などがあります。今回は前者の方法を使って、空中でジャンプできないようにします。

二段ジャンプ禁止のプログラミング

追加したプログラムは、15行目のisJumping変数、29行目のisJumping変数の値をtrueにする処理、34~40行目のisJumping変数の値をfalseにする処理です。変更したプログラムは、19行目のジャンプの判定です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(CapsuleCollider2D))]

public class PlayerController : MonoBehaviour
{
    [SerializeField] private Rigidbody2D rb;

    [SerializeField] private int moveSpeed;
    [SerializeField] private int jumpForce;

    private bool isJumping = false;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && !isJumping && !(rb.velocity.y < -0.5f))
        {
            Jump();
        }

        rb.velocity = new Vector2(Input.GetAxis("Horizontal") * moveSpeed, rb.velocity.y);
    }

    void Jump()
    {
        isJumping = true;

        rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
    }

    void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag("Stage"))
        {
            isJumping = false;
        }
    }
}

それでは解説していきます。

15行目のisJumping変数は、ジャンプしているかどうかの値を保持する変数です。インスペクターから値を設定する必要はなく、クラス内でのみ使用する変数ですので、[SerializeField]はつけずにprivate変数にしています。

29行目は、ジャンプした情報をisJumping変数に代入しています。

34~40行目は、着地した情報をisJumping変数に代入しています。OnTriggerEnter2D関数はRigidbody 2Dの「Is Trigger」にチェックを入れているCollider 2Dが、他のCollider 2Dと接触した時に呼び出されます。 プレイヤーの当たり判定に使用しているCollider 2Dを使用すると、天井に当たった場合でも着地した判定になってしまいますので、着地判定用のCollider 2Dを新たに追加します。
また、ステージと触れたときのみ着地判定にしたいので、TagというUnityの機能を使用しました。タグはオブジェクトごとに設定することができ、条件をオブジェクトごとに定めたい時に活用できます。この後、Tilemapのオブジェクトに「Stage」という名前のタグを設定しますので、接触したTriggerのTagが「Stage」かどうかの条件を追加しています。

19行目は、スペースキーが押されたかつisJumping変数の値がfalseの場合にジャンプするプログラムになるように、プログラムを変更しました。

以上で、二段ジャンプを禁止するプログラムは完成です。

着地判定用のCollider2Dを追加

プレイヤーのオブジェクトを選択し、「Add Component > Physics 2D > Capsule Collider 2D」をクリックします。

着地判定用のCollider2Dの設定

まず、「Is Trigger」にチェックを入れます。「Is Trigger」は、Collider 2D同士が衝突しても貫通するようになります。そのため、物理演算で衝突させたくない場合に当たり判定を実装したい時に活用できます。

次に、Colliderの位置と大きさを足元に合わせて調節します。OffsetのXを「0」・Yを「-0.315」、SizeのXを「0.39」・Yを「0.1」に設定しました。

最後に、元のプレファブに変更を反映させるために、「Overrides > Apply All」をクリックします。

タグの設定方法

タグの設定は、追加する手順と適応する手順があります。

タグの追加

何かしらのオブジェクトを選択した後、「Tag > Add Tag…」をクリックします。

タグ追加画面の開き方

すると、タグやレイヤーを管理する画面に遷移します。

Tagsの右下にある「+」ボタンをクリックして「Stage」と名前をつけた後、Saveをクリックします。

タグの追加

これで、「Stage」というタグが追加できました。

タグの適用

Tilemapのオブジェクトに「Stage」というタグを適用します。

Tilemapのオブジェクトを選択して、「Tag > Stage」をクリックします。

タグの適応

タグの設定は以上です。

最終確認

最後に動作確認をします。プレイボタンをクリックしてください。

最終確認

空中でスペースキーを押してもジャンプすることはなく、一回だけジャンプできるようになりましたね。

使用アセット一覧

「Unityで2Dアクションゲームの作り方を解説」で紹介・使用するアセットは全て無料のものです。
以下は、現在使用中のアセットです。

次回について

次回は、プレイヤーが静止時・移動時・ジャンプ時のアニメーションを追加します。

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