コンテンツへスキップ

【Unity 2D アクションゲーム】② プレイヤーの作成


STEP1:プロジェクトビューにプレイヤーの画像を登録する

unity-2d-action2-1

左図のように、Assets フォルダに Player フォルダを作成します。

unity-2d-action2-2

アセットストアでダウンロードしてきたプレイヤーの画像を、先ほど作った「Player」フォルダにコピペします。

アセットストアから画像をインポートする方法はこちらの記事が参考になります。お気に入りの画像を探してみましょう。

STEP2:プレイヤーをゲーム画面に配置する

unity-2d-action2-3

プレイヤーを配置する前に、Unity エディタが「シーン」ビューを表示していることを確認してください。「ゲーム」ビューの場合はオブジェクトの追加ができません。

また、「シーン」ビュー内の「ツールパレット」のいずれかを選択しておきます。「タイルパレット」を選択していると意図せずタイルマップを編集してしまうことがあるためです。

unity-2d-action2-4

次の手順でプレイヤーをゲーム画面に配置します。

 ① プロジェクトの Assets フォルダから、プレイヤーの画像をヒエラルキーにドラッグアンドドロップする

 ② オブジェクト名を Player に変更する

 ③ ソートレイヤー「Player」を作成し、前面に表示させる

unity-2d-action2-5

「ツールパレット」を使って、プレイヤーの大きさや最初の位置を調整します。

STEP3:プレイヤーに重力をつける

Unity には、重力を計算してくれるコンポーネント(部品)があります。ここでは、プレイヤーにそのコンポーネントを付けて、ゲームの世界に重力を取り入れたいと思います。

重力がない世界では、プレイヤーは右図のようにずっと宙に浮いたままになりますよ。

重力なし

① ヒエラルキーの中から「Player」を選択します

② インスペクタービューの下にある「コンポーネントを追加」をクリックします

unity-2d-action2-6

③ 「Physics 2D」を選択します

unity-2d-action2-7

Physics とは「物理」の意味です

④ 「Rigidbody 2D」を選択します

unity-2d-action2-8

Rigidbody とは「剛体」の意味です。重力の他に摩擦などの計算も可能です。

下記の左図のように、「Player」のインスペクターに「Rigidbody 2D」が表示されていれば OK です。ただしこのままだと、地面をすり抜けて落ちていきます。そこで次に「Player」と「Ground」に当たり判定を設定します。

unity-2d-action2-9

STEP4:当たり判定をつける

Player に当たり判定を設定

① ヒエラルキーの中から「Player」を選択します

② インスペクタービューの下にある「コンポーネントを追加」をクリックします

unity-2d-action2-6

③ 「Physics 2D」を選択します

unity-2d-action2-7

④ 「Capsule Collider 2D」を選択します

unity-2d-action2-10

「Collider」は、当たり判定の範囲を指定する際に使用します。

⑤ 「Player」のインスペクターに「Capsule Collider 2D」が追加されていると思います。その中の「コライダーの編集」をクリックします。

unity-2d-action2-11

⑥ プレイヤーの当たり判定の範囲が表示されます。点の部分をつかんで、プレイヤーのサイズに合わせます。

unity-2d-action2-12

⑦ 下図のように、プレイヤーの当たり判定を設定します。

unity-2d-action2-13

Ground(地面) に当たり判定を設定

① ヒエラルキーの中から「Ground」を選択します

② インスペクタービューの下にある「コンポーネントを追加」をクリックします

unity-2d-action2-14

③ 「Physics 2D」を選択します

unity-2d-action2-7

④ 「Box Collider 2D」を選択します

unity-2d-action2-15

⑤ 「Ground」のインスペクターに「Box Collider 2D」が追加されていると思います。その中の「コライダーの編集」をクリックします。

unity-2d-action2-16

⑥ 地面の当たり判定の範囲が表示されます。点の部分をつかんで、地面のサイズに合わせます。

unity-2d-action2-17

背景(Back)を非表示にすることで、地面の形が分かりやすくしています。

⑦ 下図のように、地面の当たり判定を設定します。

unity-2d-action2-18

重力の検証

下記のように、地面のところで止まるようになれば、重力の設定は完成です。

STEP5:横移動

横移動に関しては、C# スクリプト(プログラム)で制御します。

① プロジェクトビューの中の「Scripts」フォルダを右クリック ⇒ 「作成」 ⇒ 「C# スクリプト」と選択し、スクリプトファイルを作成します

② ファイル名を、「PlayerController」とします

unity-2d-action2-30

③ 作成したスクリプトファイルを「Player」に紐づけます。下図のようにファイルを「Player」の「インスペクタービュー」の空いているスペースにドラッグアンドドロップします

④ 成功すれば、「インスペクタービュー」内に「PlayerController」が表示されます(下図の青枠)

unity-2d-action2-31

インスペクタービュー内の「PlayerController」をダブルクリックします。Visual Studio が起動するので、これを使って下記のようにプログラミングします。ダブルクリックしても Visual Studio が起動しない場合は、こちらの記事を見て設定してみてください。

プレイヤーがコロコロと転がって移動することがあります。Q & A に解決方法を記載しているのでこちらを参考にしてみてください。

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float Scale;

    private Rigidbody2D rbody;
    private float axisH;

    /// <summary>
    /// Start is called before the first frame update
    /// シーンに読み込まれたときに1回だけ実行される
    /// </summary>
    private void Start()
    {
        rbody = GetComponent<Rigidbody2D>();
        transform.localScale = new Vector2(Scale, Scale);
    }

    /// <summary>
    /// Update is called once per frame
    /// 入力系の処理を記述するところ
    /// </summary>
    private void Update()
    {
        axisH = Input.GetAxisRaw("Horizontal");
        if (axisH < 0.0f)  // 左を向く
        {
            transform.localScale = new Vector2(-1 * Scale, Scale);
        }
        else if (0.0f < axisH)  // 右を向く
        {
            transform.localScale = new Vector2(Scale, Scale);
        }
    }

    /// <summary>
    /// 物理演算を使う移動系の処理を記述するところ
    /// </summary>
    private void FixedUpdate()
    {
        rbody.velocity = new Vector2(axisH * 3.0f, rbody.velocity.y);
    }
}

プログラム解説

■5行目:Scale(変数)
 プレイヤーの大きさ(スケール)を設定します。
 public がついている理由は Q & A に記載しています。

■ 7行目:rbody(変数)
 プレイヤーに追加したコンポーネント(Rigidbody2D)を保存します
 実際に取得するのは、16行目のコードです
 横移動の際に利用します(42行目)

■8行目:axisH(変数)
 入力された水平方向のキー(左・右の矢印キー)の値を保存するための変数です
 24行目の Update メソッド内で取得します
 (右矢印キー:+1  左矢印キー:ー1)

■27 ~ 34行目:if 文
 左矢印キーが押されたら左に向く
 右矢印キーが押されたら右を向く

■40行目:FixedUpdate(メソッド)
 入力された水平方向のキーの値によって、プレイヤーを横移動させます
 重力による移動を忘れないようにします(rbody.velocity.y)

STEP6:ジャンプ

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float Scale;
    public float Jump;

    [SerializeField] private float groundCheckRadius;
    [SerializeField] private float groundCheckOffsetY;
    [SerializeField] private float groundCheckDistance;
    [SerializeField] private LayerMask groundLayer;

    private Rigidbody2D rbody;
    private float axisH;
    private bool goingJump = false;

    /// <summary>
    /// Start is called before the first frame update
    /// シーンに読み込まれたときに1回だけ実行される
    /// </summary>
    private void Start()
    {
        rbody = GetComponent<Rigidbody2D>();
        transform.localScale = new Vector2(Scale, Scale);
    }

    /// <summary>
    /// Update is called once per frame
    /// 入力系の処理を記述するところ
    /// </summary>
    private void Update()
    {
        axisH = Input.GetAxisRaw("Horizontal");
        if (axisH < 0.0f)  // 左を向く
        {
            transform.localScale = new Vector2(-1 * Scale, Scale);
        }
        else if (0.0f < axisH)  // 右を向く
        {
            transform.localScale = new Vector2(Scale, Scale);
        }

        // ジャンプ
        if (Input.GetButtonDown("Jump"))
        {
            goingJump = true;
        }
    }

    /// <summary>
    /// 物理演算を使う移動系の処理を記述するところ
    /// </summary>
    private void FixedUpdate()
    {
        rbody.velocity = new Vector2(axisH * 3.0f, rbody.velocity.y);

        // ジャンプ
        if (OnGround() && goingJump)
        {
            Vector2 jumpPw = new Vector2(0, Jump);
            rbody.AddForce(jumpPw, ForceMode2D.Impulse);
            goingJump = false;
        }
    }

    /// <summary>
    /// 着地しているかどうかの判定
    /// </summary>
    /// <returns></returns>
    private bool OnGround()
    {
        return Physics2D.CircleCast((Vector2)transform.position + (groundCheckOffsetY * Vector2.up), groundCheckRadius, Vector2.down, groundCheckDistance, groundLayer);
    }

    /// <summary>
    /// CircleCastのレイを可視化(プログラムから呼んではいけない)
    /// </summary>
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawWireSphere((Vector2)transform.position + (groundCheckOffsetY * Vector2.up) + (Vector2.down * groundCheckDistance), groundCheckRadius);
    }
}

プログラム解説

■6行目:Jump(変数)
 プレイヤーのジャンプ力を設定します。

■8~11行目:SerializeField(変数)
 プレイヤーが地面に着地しているか判定するために使用する変数です
 SerializeField は、private な変数を、Unity エディタ側からアクセスできるようにするための修飾子です

■15行目:goingJump(変数)
 スペースキーが押されたときに True になる(44行目)
 ジャンプしたら False になる(62行目)

■58行目:if 文
 「地面に着地している」かつ「スペースキーが押された」ときに
 ジャンプします

■70行目:OnGround()
 地面に着地しているかの判定を行う
 判定には、CircleCast という「レイヤー(Ground)」との接触を感知するメソッドを利用します

なお、CircleCast を使う場合、レイヤーを Unity 側で設定する必要があります。下記の手順に従って設定します。

① ヒエラルキーから「Ground」を選択し、レイヤー「Ground」を設定します。レイヤーに「Ground」がない場合は追加します。

unity-2d-action2-40

② ヒエラルキーから「Player」を選択し、赤枠部分を入力します。下表のように入力しました。

unity-2d-action2-41
項目設定値(例)
スケール7
ジャンプ9
Ground Check Radius0.5
Ground Check Offset Y-0.7
Ground Check Distance0
Ground LayerGround

ここまで完成すれば、このように横移動やジャンプができるようになります。

Q1. プレイヤーが横移動をするとコロコロと転がる

コライダーの形によっては、プレイヤーがコロコロと転がることがあります。この場合は、プレイヤーのインスペクター内「Rigidbody 2D」のConstraints「回転を固定」にチェックを入れます。このように設定すると、コロコロと回転しなくなります。

unity-2d-action2-32

Q2. 変数に public がついている理由

public とは、「公開する」という意味です。Unity の C# スクリプト内で public な変数を作成すると、下図のように Unity エディタ側でその変数の値を変更することができます。

private な変数を作ることもできます。private な変数の場合は、Unity エディタからその変数にアクセスできなくなります。同じ C# スクリプト内からしかアクセスできないようになります。基本的には private な変数を定義するようにします。

unity-2d-action2-90

Q3. 着地判定をしている CircleCast の範囲を確認したい

以下のプログラムを記述するだけです。他のコードから実行する必要はありません。

    /// <summary>
    /// CircleCastのレイを可視化(プログラムから呼んではいけない)
    /// </summary>
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawWireSphere((Vector2)transform.position + (groundCheckOffsetY * Vector2.up) + (Vector2.down * groundCheckDistance), groundCheckRadius);
    }

上記のコードを記述したら、Unity エディタを開き、赤枠内の変数の値を変更します。そうすると、シーン上に CircleCast の範囲が表示されます。これを見ながら調節することになります。

unity-2d-action2-91