【Unity】プレイヤーのC#スクリプトの書き方(ゲームの作り方チュートリアル「悪路王」その3)

悪路王 プレイヤーキャラ ゲームの作り方

前回、プレイヤーキャラクターのアニメーションの設定を行いました。しかしまだプレイヤーを動かすためのC#スクリプトを書いていないので、このままではプレイヤーキャラは動きません。

そこでここではプレイヤーキャラクター用のC#スクリプトを書き、キャラクターが動くようにしていきます。

今回のゲームのプレイヤーキャラの仕様・仕組み

まずは今回のゲーム「悪路王」のプレイヤーキャラクターの仕様や仕組みを整理し、C#スクリプトの処理を理解しやすくしておきましょう。

仕様

はじめに今回のゲームのプレイヤーキャラの仕様は次のようになっています。

  • プレイヤーがSpaceキーを押すとキャラクターがジャンプする。
  • ジャンプはキャラクターが地面に接地しているときのみ行うことができる。
  • ジャンプ以外の移動は行わない。
  • 地面に接地しているかどうかでアニメーションの状態を変化させる。

ジャンプだけのゲームなのでとてもシンプルですね。複雑な処理は必要ないので比較的短いC#スクリプトで済みそうです。

ジャンプの仕組み

さて仕様についてご説明したところで、今回のキャラクターの動きの肝となるジャンプについてその仕組みをご説明しておこうと思います。アクションゲームといえばジャンプは当たり前にあるものなため「そんなの知ってるよ」と思うかもしれませんが、ジャンプの実装は初心者の方には意外と難しいので面倒でも目を通しておいていただければと思います。

今回のジャンプ処理の流れは次のような感じになっています。

  1. 毎フレーム接地判定を行う
  2. プレイヤーのキー入力を受け付ける
  3. もしキー入力があり、かつ接地しているならジャンプ処理を行う

それぞれ詳しく見てみましょう。

接地判定

まず最初にして一番の難題が接地判定です。Unity初心者の方はまず接地判定でつまづくといっても過言ではないと思うので、やり方をきちんと知っておく必要があります。

キャラクターが地面に接地しているかどうかを判定する方法はいくつかあるのですが、ここではレイキャストを使った方法を採用することにします。レイキャストとは簡単に言えば「透明な光線を発射し、離れた場所にある物体を検出する」ことです。

つまり、ここでは光線を下向きに発射して地面があるかどうかを調べるというわけですね。この方法は精度の高い接地判定を比較的簡単に作れるのでおすすめです。

なおレイキャストを使った接地判定についての詳細は姉妹サイトのほうで詳しく解説しているので、そちらも併せてご覧頂ければと思います。

【Unity】アクションゲームの「接地判定」の作り方!Raycastを使って地面を検出してみよう
今回はUnity初心者の方向けの話題で、 アクションゲームで必須の「接地判定」の作り方 を丁寧に解説するという内容になっています。 アクションゲームを作っていると、まず確実にジャンプなどのアクションを実装することになると思うのですが、その際

キー入力の受付

次にキー入力の受付については、Update関数内で処理を行います。キー入力の受付はよほどの理由がない限りはUpdate関数内で行う必要があります。なぜならUnityのキー入力処理はUpdate関数に合わせて作られているからです。FixedUpdate関数とかで処理を行うとキー入力を取りこぼす可能性があるので注意しましょう。

ちなみにUnityのキー入力の処理は

  • 最新の「Input System」
  • 旧式の「Input Manager」(デフォルト)

の2種類があるのですが、今回は簡単な「Input Manager」のほうを採用します。もし新しいInput Systemのほうを使ってみたいなぁという方は姉妹サイトのほうに使い方を詳しく書いてあるので、そちらも併せてご覧頂ければと思います。

【Unity】Input System(新しい入力システム)の使い方
Unityでキーボード・マウス・ゲームパッド等の入力を扱うやり方といえば、従来は Input Managerでボタン等を設定し、 Inputクラスで入力を取得する という方法が一般的でした。ただしこのやり方は単純で分かりやすい反面、例えば色

ジャンプ処理

最後にキー入力があり、かつ接地しているならジャンプを行います。ジャンプ処理にはUnityに組み込まれている物理演算を使用します。

プレイヤーキャラクター用のC#スクリプト

では前置きが長くなってしまいましたが、ここからが本題でプレイヤーキャラクター用のC#スクリプトを書いていきます。

プロジェクトビューで適当なフォルダの何もないところを右クリックし、「作成」→「C#スクリプト」から新しいC#スクリプトファイルを作ります。このとき名前変更モードになっていると思うので、その状態でスクリプト名を「Player」に変更しておきます(※こうすることでC#スクリプト内のクラス名も自動的にファイル名と同じになります)。

そうしたら次のソースコードを書いてください。

using UnityEngine;

public class Player : MonoBehaviour
{

    [SerializeField]
    Rigidbody2D rigidBody2D;
    [SerializeField]
    Animator animator;
    [SerializeField]
    float jumpPower = 20;
    [SerializeField]
    float groundCheckRadius = 0.4f;
    [SerializeField]
    float groundCheckOffsetY = 0.45f;
    [SerializeField]
    float groundCheckDistance = 0.2f;
    [SerializeField]
    LayerMask groundLayers = 0;

    bool isGrounded = false;

    public bool IsActive { get; set; } = true;

    void Update()
    {
        if (!IsActive)
        {
            return;
        }

        isGrounded = CheckGroundStatus().collider != null;
        GetInput();
        UpdateAnimator();
    }

    // 入力受付
    void GetInput()
    {
        if (isGrounded && Input.GetButtonDown("Jump"))
        {
            Jump();
        }
    }

    // 接地判定
    RaycastHit2D CheckGroundStatus()
    {
        return Physics2D.CircleCast((Vector2)transform.position + groundCheckOffsetY * Vector2.up, groundCheckRadius, Vector2.down, groundCheckDistance, groundLayers);
    }

    // ジャンプ
    void Jump()
    {
        rigidBody2D.AddForce(jumpPower * Vector2.up, ForceMode2D.Impulse);
    }

    // アニメーターの更新
    void UpdateAnimator()
    {
        animator.SetBool("Grounded", isGrounded);
    }

}

C#スクリプトの解説

レイキャストによる接地判定

まずCheckGroundStatus関数で接地判定を行います。上で説明したとおり、接地判定にはレイキャストを使っていますが普通のレイキャストではなくCircleCastという円状の光線を発射することで、より精度の高い接地判定を行えるようにしています。

キー入力の受付

キー入力の受付に関しては、キーを押し下げた瞬間にだけジャンプを行いたいのでInput.GetButtonDown関数を使っています。

物理演算によるジャンプ処理

ジャンプ処理についてはRigidbody2DクラスのAddForce関数を使って物理的に力を加えることで実現しています。このAddForce関数の第二引数には力を加えるときのモードを指定できるのですが、ここでは一瞬だけ力を加えたいのでForceMode2D.Impluseを指定しています。

ちなみにこの処理は根本的にはUpdate関数から呼ぶことになっているので、Unityにちょっと詳しい方なら「物理演算の関数をUpdate関数から呼んでいいの?」と思うかもしれませんね。しかしここでは一瞬だけ力を加えてあとは何もしないので特に問題はありません。

アニメーターのステートの更新

最後にUpdateAnimator関数でアニメーターのステートを更新します。これにより前回作ったアニメーションが正常に切り替わるようになります。

プレイヤーキャラクターに必要なコンポーネントをアタッチし、テストプレイしてみよう

さてこれでひとまずC#スクリプトができたので、あとはプレイヤーのゲームオブジェクトに必要なコンポーネントをアタッチしてテストプレイしてみましょう。

必要なコンポーネントのアタッチ&設定

まず、このままでは物理演算に必要なコンポーネントがアタッチされておらず、物理的な移動ができないのでその辺のコンポーネントを取り付けます。必要なコンポーネントは次の2つです。

  1. Rigidbody 2D
  2. Capsule Collider 2D

コンポーネントはインスペクターの下の方の「コンポーネントを追加」ボタンから追加できます。ここではどちらも2Dゲーム用のものを使うので注意してください。

これらをアタッチできたら、先ほど作ったC#スクリプトをインスペクターにドラッグ&ドロップしてプレイヤーのゲームオブジェクトにアタッチし、下のように設定を行ってください。

プレイヤーキャラクターのコンポーネントの設定

  • Playerスクリプト
    • Rigidbody2D・アニメーター:Player自身のものを登録
    • Ground Layers:「Default」を指定
    • Jump Power:お好みで変更(そのままでもよい)
  • Rigidbody2D
    • 回転抗力:0
    • 重力スケール:5
      (※デフォルトだとフワッとした動きになるので、重力を大きめにしてゲームらしい動きにする。値はお好みでOK)
    • 衝突判定:連続的
    • スリープモード:スリープしない
    • 補間:補間
    • 回転を固定:チェックをON
      (※これをONにしないとキャラクターがコケてしまう)

動作の確認

ではゲームを実行してテストプレイしてみましょう。といっても今のままでは地面がなくキャラクターが落ちてしまうので、テスト用の地面を用意します。

最初にインポートしてもらった画像素材の中に「floor」という四角い画像があると思うので、それをシーンにドラッグ&ドロップし、Box Collider 2Dコンポーネントをアタッチします。そうしたらスケールを適当に大きくしてプレイヤーの下に床を配置しておきましょう。

ここまでできたらUnityエディタ上部の再生ボタンを押してゲームを実行してみましょう。次のGIFのようにSpaceキーを押したらプレイヤーがジャンプするようになれば成功です。

悪路王 プレイヤーキャラクターの動きの例

(画像クリックでGIF再生)

次のページ

【Unity】動く障害物の作り方(ゲームの作り方チュートリアル「悪路王」その4)
前回、プレイヤーのC#スクリプトを書いてプレイヤーキャラクターが動くようになりました。次は障害物を動かすC#スクリプトを書いてみましょう。 前提:プレイヤーではなく「障害物を動かす」という発想 さてはじめにそもそもの話なんですけど、今回のゲ...