君がゲームを作る!Unityゲーム開発入門
第28回 キャラクターをジャンプさせる(後編)

ファッションでの「重ね着」のことをレイヤードって言うよね

こんにちは!

普段からユニクロのスウェット上下姿で仕事をしているので、 たまに着替えると、デニムパンツですら変な気合が入るあらたまです!

さて、今日はUnity入門の第28回目。今回も引き続きキャラクターのジャンプを作っていきたいと思います!

おさらい

前回 では、スペースキーを押すとキャラクターがジャンプするようにしましたね。

しかし、空中でスペースキーを押すと、何度でも多段ジャンプができてしまいました。

今回は、その多段ジャンプができないように変更していきましょう!

変更の手順

まず最初に今回の手順をお伝えすると

  • タイルマップに「レイヤー」を割り当てる
  • キャラクターが「レイヤー」に接触しているときだけ、ジャンプ処理を有効にする
という手順で行います。

どうやら今回のポイントは「レイヤー」になりそうですね。それでは始めていきましょう!

「レイヤー」ってなに?

レイヤー(Layer)」は単語としては「層」や「階層」という意味です。

「複数重なっているもののうちの一部」という意味ですね。 日本語では「オゾン層」とか「高層階」とかの言葉に入っています。

Unityでは「レイヤー」をゲームオブジェクト同士の重なり順を設定するのに使います。 背景よりキャラクターは前面に、キャラクターより得点数を前面に表示する、というような感じですね。

地面用の「レイヤー」を準備する

ヒエラルキーウィンドウで「Tilemap」を選択したあと、 インスペクターウィンドウで「Layer」のセレクトボックスをクリックします。

「Add Layer」をクリックします。

レイヤーの一覧が表示されました。
「Builtin Layer」となっているのは、Unity側であらかじめ準備されているレイヤーです。

「User Layer」が自分で自由に定義できるレイヤーです。

今回は地面用のレイヤーを作りたいので「User Layer 8」に「Ground」というレイヤー名を付けます。

タイルマップに地面用のレイヤーを割り当てる

もう一度、インスペクターウィンドウで「Layer」のセレクトボックスをクリックします。

インスペクターウィンドウで「Layer」のセレクトボックスをクリックすると

さきほど入力した「Ground」レイヤーが選択肢に表示されています!
これをクリックすると、、

タイルマップが「Ground」レイヤーに割り当てられました。

「レイヤー」に接触しているときだけ、ジャンプ処理を有効にする

つづいて地面に接地しているとき(Groundレイヤーに接触しているとき)だけ、ジャンプできるようにしていきましょう!

プロジェクトウィンドウで「Scripts」フォルダを選択し、 「CharaControl」ァイルを選択後インスペクターウィンドウで「Open」をクリックします。

スクリプトの編集画面(プログラミング画面)が表示されました!

現在のスクリプトの状態はこのようになっていますね。

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

public class CharaControl : MonoBehaviour {

    // キャラクターの移動スピード(インスペクターウィンドウで値を設定)
    public float speed;

    // Rigidbody2Dを保持するメンバ変数
    private Rigidbody2D rb2d;

    // ジャンプ力
    public float jumpForce;

    // コンポーネントの初期化処理
    void Start()
    {
        // ゲームオブジェクトが持っているRigidbody2Dコンポーネントを
        // 取得してメンバ変数に保持
        rb2d = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        if (Input.GetKeyDown("space"))
        {
            rb2d.AddForce(Vector2.up * jumpForce);
        }
    }

    // 画面表示更新処理
    void FixedUpdate()
    {
        // 横矢印キーの押されている状況を取得
        float moveHorizontal = Input.GetAxis("Horizontal");

        // AddForceメソッドに渡すために、Vector2型に変換
        Vector2 movement = new Vector2(moveHorizontal, 0);

        // AddForceメソッドでキャラクターのRigidbody2Dコンポーネントに力を加える
        rb2d.AddForce(movement * speed);
    }
}

ここに太字の部分を追加します。

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

public class CharaControl : MonoBehaviour {

    // キャラクターの移動スピード(インスペクターウィンドウで値を設定)
    public float speed;

    // Rigidbody2Dを保持するメンバ変数
    private Rigidbody2D rb2d;

    // ジャンプ力
    public float jumpForce;
    // 地面用レイヤー
    public LayerMask groundlayer;

    // コンポーネントの初期化処理
    void Start()
    {
        // ゲームオブジェクトが持っているRigidbody2Dコンポーネントを
        // 取得してメンバ変数に保持
        rb2d = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        if (Input.GetKeyDown("space"))
        {
            bool grounded = Physics2D.Linecast(transform.position,
                            transform.position - transform.up,
                            groundlayer);

            if (grounded){
                rb2d.AddForce(Vector2.up * jumpForce);
            }
        }
    }

    // 画面表示更新処理
    void FixedUpdate()
    {
        // 横矢印キーの押されている状況を取得
        float moveHorizontal = Input.GetAxis("Horizontal");

        // AddForceメソッドに渡すために、Vector2型に変換
        Vector2 movement = new Vector2(moveHorizontal, 0);

        // AddForceメソッドでキャラクターのRigidbody2Dコンポーネントに力を加える
        rb2d.AddForce(movement * speed);
    }
}

groundlayer

メンバ変数のgroundlayerは地面とするレイヤーを保持します。
ここに入る値は、インスペクタビューで設定します。

grounded = Physics2D.Linecast

「Physics2D.Linecast」は、第一引数と第二引数で指定された点を結ぶ直線が、 第三引数で指定されたレイヤーに接触していたらtrueを返す命令です。

第一引数の「transform.position」はスプライトの中心点です。

第二引数で使われている「transform.up」は、スプライトの中心点から上端の長さです、つまりはスプライトの高さの半分ですね。
これを「transform.position(スプライトの中心点)」から引くことにより、スプライトの下端を求めています。

第三引数にはメンバ変数「groundlayer」を指定しています。

まとめると、「スプライトの中心点から下端を結んだ直線」が「地面とするレイヤー」に接触していればtrueを変数「grounded」に入れている、ということですね。

if (grounded)

上で値を設定したgroundedがtrueであった場合のみ、ジャンプを実行しています。

メンバ変数「groundlayer」を設定する

続いて、メンバ変数「groundlayer」の値を設定します。

シーンビューでキャラクターを設定した状態で、 インスペクターウィンドウの「Groundlayer」で「Ground」を選択します。

「Groundlayer」に「Ground」が設定されました!

テストプレイで動作確認をする

それでは、テストプレイをして変化を確認してみましょう!

▶ボタンを押して、プレイモードに入ります。

キャラクターが地面に接地してるときのみ、ジャンプできるようになりました!

今回はここまでです!

次回からはキャラクターにアニメーションをつけていきたいと思います。

次回へ続く。

>> 続きの記事
【君がゲームを作る!Unityゲーム開発入門】第29回 キャラクターをアニメーションする