前回、プレイヤーキャラクターのアニメーションの設定を行いました。しかしまだプレイヤーを動かすためのC#スクリプトを書いていないので、このままではプレイヤーキャラは動きません。
そこでここではプレイヤーキャラクター用のC#スクリプトを書き、キャラクターが動くようにしていきます。
今回のゲームのプレイヤーキャラの仕様・仕組み
まずは今回のゲーム「悪路王」のプレイヤーキャラクターの仕様や仕組みを整理し、C#スクリプトの処理を理解しやすくしておきましょう。
仕様
はじめに今回のゲームのプレイヤーキャラの仕様は次のようになっています。
- プレイヤーがSpaceキーを押すとキャラクターがジャンプする。
- ジャンプはキャラクターが地面に接地しているときのみ行うことができる。
- ジャンプ以外の移動は行わない。
- 地面に接地しているかどうかでアニメーションの状態を変化させる。
ジャンプだけのゲームなのでとてもシンプルですね。複雑な処理は必要ないので比較的短いC#スクリプトで済みそうです。
ジャンプの仕組み
さて仕様についてご説明したところで、今回のキャラクターの動きの肝となるジャンプについてその仕組みをご説明しておこうと思います。アクションゲームといえばジャンプは当たり前にあるものなため「そんなの知ってるよ」と思うかもしれませんが、ジャンプの実装は初心者の方には意外と難しいので面倒でも目を通しておいていただければと思います。
今回のジャンプ処理の流れは次のような感じになっています。
- 毎フレーム接地判定を行う
- プレイヤーのキー入力を受け付ける
- もしキー入力があり、かつ接地しているならジャンプ処理を行う
それぞれ詳しく見てみましょう。
接地判定
まず最初にして一番の難題が接地判定です。Unity初心者の方はまず接地判定でつまづくといっても過言ではないと思うので、やり方をきちんと知っておく必要があります。
キャラクターが地面に接地しているかどうかを判定する方法はいくつかあるのですが、ここではレイキャストを使った方法を採用することにします。レイキャストとは簡単に言えば「透明な光線を発射し、離れた場所にある物体を検出する」ことです。
つまり、ここでは光線を下向きに発射して地面があるかどうかを調べるというわけですね。この方法は精度の高い接地判定を比較的簡単に作れるのでおすすめです。
なおレイキャストを使った接地判定についての詳細は姉妹サイトのほうで詳しく解説しているので、そちらも併せてご覧頂ければと思います。
キー入力の受付
次にキー入力の受付については、Update関数内で処理を行います。キー入力の受付はよほどの理由がない限りはUpdate関数内で行う必要があります。なぜならUnityのキー入力処理はUpdate関数に合わせて作られているからです。FixedUpdate関数とかで処理を行うとキー入力を取りこぼす可能性があるので注意しましょう。
ちなみにUnityのキー入力の処理は
- 最新の「Input System」
- 旧式の「Input Manager」(デフォルト)
の2種類があるのですが、今回は簡単な「Input Manager」のほうを採用します。もし新しいInput Systemのほうを使ってみたいなぁという方は姉妹サイトのほうに使い方を詳しく書いてあるので、そちらも併せてご覧頂ければと思います。
ジャンプ処理
最後にキー入力があり、かつ接地しているならジャンプを行います。ジャンプ処理には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つです。
- Rigidbody 2D
- 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キーを押したらプレイヤーがジャンプするようになれば成功です。