うまげーむさん

ゲームの情報を主に投稿します。

【Unity】ソースコードコピペ可能!マリオ風2Dアクションゲームの作り方 #5 着地判定 / カメラ追従 / デス判定

はじめに

どうも。今日も今日とて、Unityです。

前回はアニメーションの実装を行いました。今回はジャンプが空中で出来てしまう不具合の修正と、マップの拡張・カメラの移動設定・デス判定の追加を行います。

前回:

www.umagame.info

着地判定

レイヤーの追加

まず、地面に足がついている状態でのみジャンプできるようにプレイヤーのスクリプトを修正します。

まず、「地面」を定義するために、第2回で追加したTerrainのタイルマップのレイヤーを設定します。

「レイヤー」→「レイヤーを追加」をクリック。

インスペクターでレイヤー設定の画面が表示されるので、Groundという名前のレイヤーを追加します。

ここで注意ですが、このレイヤーは第2回で設定した「ソートレイヤー」とは別物です。

「ソートレイヤー」は表示上の設定に使いますが、こちらの「レイヤー」は主に衝突判定の設定で使います。なので、上の設定画面でのレイヤーの上下関係は関係ありません。

Terrainのインスペクターでレイヤーを設定しておきます。

スクリプトの編集

では、Player.csを編集していきます。

//Player.cs

public class Player : MonoBehaviour
{
    
    public LayerMask GroundLayer;

    void Update()
    {
        if (Input.GetButtonDown("Jump") && isGrounded())
        {
            rb.velocity = new Vector2(rb.velocity.x, JumpForce);
        }
    }

    private bool isGrounded()
    {
        BoxCollider2D c = GetComponent<BoxCollider2D>();
        return Physics2D.BoxCast(c.bounds.center, c.bounds.size, 0f, Vector2.down, .1f, GroundLayer);
    }
}

新しくboolを返すisGrounded()というメソッドを追加し、Update()のジャンプを実装していたif文の条件にisGroundedを追加します。

isGroundedでは、Physics2D.BoxCastというメソッドを使って接地判定を行っています。BoxCastは矩形の当たり判定を移動させて他のオブジェクトとの衝突を検知するやつらしいです。

インスペクターで、新しく追加したGroundLayerという変数(接地判定で地面と認識するレイヤー)を「Ground」に設定します。

これで、ジャンプの修正は完了です。

マップ拡張・カメラ移動

次に、マップを広げます。

今回はこんな感じに広げました。テストプレイ用なので適当です。

カメラ用スクリプト

カメラの移動を制御するスクリプトを作成します。

Assets/Scriptsで右クリック→作成→C# スクリプトをクリック。

名前はCameraMovementにします。(「Camera」という名前はUnityの仕様上使えないみたいです)

//CameraMovement.cs
public class CameraMovement : MonoBehaviour
{
    public GameObject Target;
    public GameObject LeftEdge;
    public GameObject RightEdge;

    void Start()
    {

    }

    void Update()
    {
        this.transform.position = new Vector3(Target.transform.position.x, this.transform.position.y, this.transform.position.z);

        if (this.transform.position.x <= LeftEdge.transform.position.x)
        {
            this.transform.position = new Vector3(LeftEdge.transform.position.x, this.transform.position.y, this.transform.position.z);
        }
        else if (this.transform.position.x >= RightEdge.transform.position.x)
        {
            this.transform.position = new Vector3(RightEdge.transform.position.x, this.transform.position.y, this.transform.position.z);
        }
    }
}

こんな感じです。GameObject型の変数を3つ使ってカメラの移動を制御しています。

ターゲット(Target)はカメラが追従するオブジェクトです。今回はプレイヤーオブジェクトを指定します。

左右の端(Left / RightEdge)はマップの端を検知するためのオブジェクトです。(これは後ほど追加します。)

まずカメラのX座標をターゲットのX座標にして、左右の端をターゲットが超えた際はカメラの座標を端に固定するという処理を行っています。

スクリプトを書いたら、カメラのオブジェクト(MainCamera)にドラッグアンドドロップで適用します。

端検知用オブジェクト

先述のマップの端を検知するためのオブジェクトを追加します。

右クリック→空のオブジェクトを作成をクリックして、オブジェクトを2つ作成します。

名前は「CameraLeftEdge」、「CameraRightEdge」にします。

Leftの方は現在カメラがある位置で良いので、X座標を0に設定します。(Y, Z座標は何でも良いです)

Rightはカメラの幅に合わせて設定します。今回はX=31としました。カメラの画面サイズが18x10なので、右端から9マスのところに置けばOKです。

PlayerとEdgeのオブジェクトをCameraMovementのスクリプトにドラッグして設定します。

こんな感じです。

これで、右へ移動するとプレイヤーに合わせてカメラも動くようになりました。

地形の当たり判定の修正

移動キーを押したまま壁に接触すると浮いてしまう不具合が判明したので、これを先に修正しておきます。

本当はこれを第2回にやるべきだったんですが、忘れてました。

Terrainオブジェクトに新しく「Platform Effector 2D」というコンポーネントを追加します。

そして、「Composite Collider 2D」の「エフェクターで使用」にチェックを入れて、「Platform Effector 2D」の「1方向の...」のチェックを外します。

これで直りました。

デス判定

デス判定タイルの追加

マップ外に落ちた際にゲームオーバーになるようにします。

まず、デス判定オブジェクト用のタイルのテクスチャを新たに追加します。

Assets/Textures/Tilesで右クリック→エクスプローラーで表示でテクスチャのフォルダを開き、画像ファイルを編集します。

マップ外に置くタイル用なので、見やすいように赤色ベタ塗りのテクスチャにしました。

画像ファイルを変えるだけではダメで、Sprite Editorでもう一度スライスし直す必要があります。

第2回と同じように。

追加したタイルが増えてるので、これをタイルパレットへドラッグアンドドロップで追加します。

タイルのファイルは第2回と同じAssets/Tilesに保存します。

これで新しいタイルを追加することが出来ました。

マップ変更・タイルマップの設定

デス判定を持つタイル用のタイルマップを作成します。

右クリック→2Dオブジェクト→タイルマップ→矩形をクリックします。

名前は「InstaDeathTiles」にします。

TerrainとBackgroundを編集して地形を変えて、

InstaDeathTilesでデス判定タイルを追加します。

InstaDeathTilesのインスペクターから、タグを追加します。タグ→タグを追加をクリックして、

+ボタンで新しくタグを追加します。名前はInstaDeathにします。

戻って、タグを設定します。プレイヤーがこのタグがついたオブジェクトに触れるとゲームオーバーになるようにするので、他のオブジェクトでもこのタグを適用するだけでデス判定を追加できます。

InstaDeathTilesにTilemap Collider 2Dを追加します。

これを忘れると、そもそもプレイヤーとこのタイルマップの衝突が検知されないので注意しましょう。

最後にプレイヤーのスクリプトを編集します。

//Player.cs
private void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.gameObject.CompareTag("InstaDeath"))
    {
        SceneManager.LoadScene("SampleScene");
    }
}

このメソッドを追加するだけです。

このOnCollisionEnter2Dのように、privateメソッドではありますがUnity側から特別な条件下で呼び出されるメソッドがあります。(詳しく知りたい方はこちらから)

タグがInstaDeathのオブジェクトと衝突した際に、シーンをロードし直すという処理を行っています。("SampleScene"にはシーンの名前が入ります。今回は未変更なのでSampleSceneのままです)

これで、穴に落ちると

一番最初の状態に戻るようになります。

最後に、左右の端に壁を追加するのを忘れていたので追加しておきます。

今回の進捗 / ソースコード

今回はジャンプの不具合の修正、マップの拡張、カメラの追従設定、そしてマップ外のデス判定の追加を行いました。

穴に落ちた瞬間にリセットとなっていますが、今後ゲームオーバー時の専用の画面を追加する予定なので、仮の仕様だと思っておいてください。

ソースコードは長いので、GitHubに専用のページを作ってそこに置くことにしました。(https://github.com/Umagame/TutorialGame/tree/main

今回は第5回なので、TutorialGame/5に今回作った2つのスクリプトをアップロードしています。

GitHubにWeb上から直接ファイルをアップロードしてるんですが、これGitHubの本来の使い方じゃないですよね...

まあ、スクリプトを共有できたらそれで良いです。

さいごに

今回はここまでです。

次回:

www.umagame.info