この記事はロックマン風2Dアクションの作り方講座の第5回です。
前回でタイルマップを用いたステージ制作を完了しました。ここからはそのステージを実際にプレイできるようにしていきます。
前回の記事:
まずはカメラをプレイヤーキャラの動きに合わせてついていかせる処理を実装し、前回テストプレイでは探索できなかった領域を確認できるようにしていきましょう!
そして背景画面の繰り返しや横スクロール処理にも対応させていきます。
カメラをプレイヤーキャラクターの動きに追尾させる
Unityではゲーム画面はCameraオブジェクトが対象とする範囲のみ写されています。つまりCameraオブジェクトを移動させればステージの好きな場所を表示できるようになります。
Cameraオブジェクトについては既に最初からMain Cameraというオブジェクトが存在しているのでこれを対象にします。
まずはCameraControllerクラスをお好みのフォルダに新規作成します(ここではScriptsフォルダを利用)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// メインカメラ制御クラス(Main Cameraにアタッチ) /// </summary> public class CameraController : MonoBehaviour { // オブジェクト・コンポーネント // 各種変数 private Vector2 basePos; // 基点座標 /// <summary> /// カメラの位置を動かす /// </summary> /// <param name="targetPos">座標</param> public void SetPosition (Vector2 targetPos) { basePos = targetPos; } // FixedUpdate private void FixedUpdate () { // カメラ移動 Vector3 pos = transform.localPosition; // アクターの現在位置より少し右上を映すようにX・Y座標を補正 pos.x = basePos.x + 2.5f; // X座標 pos.y = basePos.y + 1.5f; // Y座標 // Z座標は現在値(transform.localPosition)をそのまま使用 // 計算後のカメラ座標を反映 transform.localPosition = Vector3.Lerp (transform.localPosition, pos, 0.08f); } } |
- Vector3.Lerp機能を使用して、少しずつ現在位置から目標位置に移動するという処理を実現しています。
- Actorオブジェクトと全く同じ位置に移動するのではなく、目標位置を少し右上にずらすことで右方向に進行するステージの先を見やすくしています。
このクラスは自身の座標を目標位置に移動させる機能を持っているので、今回移動させたいオブジェクトであるMain Cameraにアタッチします。
そしてCameraControllerクラスにActorオブジェクトの現在位置の情報を与える為にActorControllerクラスを編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// アクター操作・制御クラス /// </summary> public class ActorController : MonoBehaviour { // オブジェクト・コンポーネント参照 private Rigidbody2D rigidbody2D; private SpriteRenderer spriteRenderer; private ActorGroundSensor groundSensor; // アクター接地判定クラス private ActorSprite actorSprite; // アクタースプライト設定クラス public CameraController cameraController; // カメラ制御クラス // 移動関連変数 [HideInInspector] public float xSpeed; // X方向移動速度 [HideInInspector] public bool rightFacing; // 向いている方向(true.右向き false:左向き) private float remainJumpTime; // 空中でのジャンプ入力残り受付時間 // Start(オブジェクト有効化時に1度実行) void Start() { // コンポーネント参照取得 rigidbody2D = GetComponent<Rigidbody2D> (); spriteRenderer = GetComponent<SpriteRenderer> (); groundSensor = GetComponentInChildren<ActorGroundSensor> (); actorSprite = GetComponent<ActorSprite> (); // 配下コンポーネント初期化 actorSprite.Init (this); // カメラ初期位置 cameraController.SetPosition (transform.position); // 変数初期化 rightFacing = true; // 最初は右向き } // Update(1フレームごとに1度ずつ実行) void Update() { // 左右移動処理 MoveUpdate (); // ジャンプ入力処理 JumpUpdate (); // 坂道で滑らなくする処理 rigidbody2D.constraints = RigidbodyConstraints2D.FreezeRotation; // Rigidbodyの機能のうち回転だけは常に停止 if (groundSensor.isGround && !Input.GetKey (KeyCode.UpArrow)) { // 坂道を登っている時上昇力が働かないようにする処理 if (rigidbody2D.velocity.y > 0.0f) { rigidbody2D.velocity = new Vector2 (rigidbody2D.velocity.x, 0.0f); } // 坂道に立っている時滑り落ちないようにする処理 if (Mathf.Abs (xSpeed) < 0.1f) { // Rigidbodyの機能のうち移動と回転を停止 rigidbody2D.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezePositionY | RigidbodyConstraints2D.FreezeRotation; } } // カメラに自身の座標を渡す cameraController.SetPosition (transform.position); } /// <summary> /// Updateから呼び出される左右移動入力処理 /// </summary> private void MoveUpdate () { // X方向移動入力 if (Input.GetKey (KeyCode.RightArrow)) {// 右方向の移動入力 // X方向移動速度をプラスに設定 xSpeed = 6.0f; // 右向きフラグon rightFacing = true; // スプライトを通常の向きで表示 spriteRenderer.flipX = false; } else if (Input.GetKey (KeyCode.LeftArrow)) {// 左方向の移動入力 // X方向移動速度をマイナスに設定 xSpeed = -6.0f; // 右向きフラグoff rightFacing = false; // スプライトを左右反転した向きで表示 spriteRenderer.flipX = true; } else {// 入力なし // X方向の移動を停止 xSpeed = 0.0f; } } /// <summary> /// Updateから呼び出されるジャンプ入力処理 /// </summary> private void JumpUpdate () { // 空中でのジャンプ入力受付時間減少 if (remainJumpTime > 0.0f) remainJumpTime -= Time.deltaTime; // ジャンプ操作 if (Input.GetKeyDown (KeyCode.UpArrow)) {// ジャンプ開始 // 接地していないなら終了 if (!groundSensor.isGround) return; // ジャンプ力を計算 float jumpPower = 10.0f; // ジャンプ力を適用 rigidbody2D.velocity = new Vector2 (rigidbody2D.velocity.x, jumpPower); // 空中でのジャンプ入力受け付け時間設定 remainJumpTime = 0.25f; } else if (Input.GetKey (KeyCode.UpArrow)) {// ジャンプ中(ジャンプ入力を長押しすると継続して上昇する処理) // 空中でのジャンプ入力受け付け時間が残ってないなら終了 if (remainJumpTime <= 0.0f) return; // 接地しているなら終了 if (groundSensor.isGround) return; // ジャンプ力加算量を計算 float jumpAddPower = 30.0f * Time.deltaTime; // Update()は呼び出し間隔が異なるのでTime.deltaTimeが必要 // ジャンプ力加算を適用 rigidbody2D.velocity += new Vector2 (0.0f, jumpAddPower); } else if (Input.GetKeyUp (KeyCode.UpArrow)) {// ジャンプ入力終了 remainJumpTime = -1.0f; } } // FixedUpdate(一定時間ごとに1度ずつ実行・物理演算用) private void FixedUpdate () { // 移動速度ベクトルを現在値から取得 Vector2 velocity = rigidbody2D.velocity; // X方向の速度を入力から決定 velocity.x = xSpeed; // 計算した移動速度ベクトルをRigidbody2Dに反映 rigidbody2D.velocity = velocity; } } |
CameraControllerへの参照をpublicで宣言しています。特にスクリプト内でGetComponentなどで取得していないので、自身でInspectorから該当のオブジェクト・コンポーネントを渡してあげる必要があります。
スクリプト更新後、ActorオブジェクトのActorControllerクラス・CameraControllerパラメータにMain Cameraオブジェクトをドラッグ&ドロップして参照を渡します(以降講座では参照をセットと呼ぶこともあります)。
これでプレイヤーキャラの動きに合わせてカメラが滑らかについてくるようになりました。
Unityで2Dアクションゲーム用ステージ背景画像を作成
現在ステージに何も背景画像を設定していないので、Unityのおける初期の背景色である青の風景が広がっているのみです(ちなみに初期背景色はCameraの設定から変更可能です)。
まずは背景画像を表示するSpriteオブジェクトとしてBackGroundを作成しましょう。Hierarchy画面で右クリック。2D > Sprites > SquareなどでSpriteRenderer持ちのゲームオブジェクトを作成。
SpriteRendererのSpriteパラメータに背景画像をセットしましょう。サンプル画像はTextures/BackGroundフォルダ以下にあります。
また、このままだとアクターやレイヤー1地形とZ座標(奥行き)が同じなので綺麗に表示できません。全てのオブジェクトより一番後ろに表示して欲しいので、Z座標は適当な大きい数値(今回は5)をセットしておきます。
Scaleも小さくて気になる場合はXとYに3~5倍程度すると良いでしょう。
背景画像を移動させて臨場感を演出しよう
現状では背景画像がその場で静止しており、距離感や立体感といったものがやや欠けています。
これはカメラの移動にあわせて背景画像を少しだけ移動させる事で改善できます。CameraControllerクラスを拡張しましょう。
まとめ
これでカメラが決められた範囲の中でプレイヤーキャラを追尾するようになりました。背景画像も設定し、ステージの端の定義も行えるようになり、制作の幅が広まりました。
今回作成した機能を活かして次回ではステージ内を複数のエリアに分割し、エリア別にカメラ移動範囲を設定した上で更にエリア間を移動する処理を実装していきます。
次の記事:
コメント
すごく分かりやすくて楽しみながら作らせてもらってます!
今回の講座の「スクリプト全文」の前にあるTile Paletteの写真は何を意味なのでしょうか。カメラ移動制限がどうしてもうまくいかずそこでも設定が必要なのかなと思い、よければ教えていただきたいです!
楽しんでもらえてるようで嬉しいです!ありがとうございます。
Tile Paletteの画像は4章の画像と同じものですね。なぜか紛れ込んだみたいです。
消しておきました。気にせず進んでもらって大丈夫です。
カメラ移動制限は講座の通り作ればできるはずです。
5章完了時点でのプロジェクトファイルを用意しておきました。
こちらも参考にしてみてください。
ありがとうございます!!
わざわざプロジェクトファイルまで用意していただき嬉しいです!!見比べると1つ順番が違っているところを見つけることができました。勝手にここは順番どっちでもいいと思ってスルーしまっていたのでとても良い勉強になりました!
これからも応援してます!