この講座はロックマン風2Dアクションゲームの作り方講座の第11回です。
前回ですべてのマップステージを作り、通常敵の配置を終えたのでステージを完成させるまで残りはボス敵の実装のみとなりました。
前回の記事:
ここからは各ステージに1体ずつのボスを作成していき、ステージクリアまで遊べるように仕上げていきましょう!
この講座で作る2Dアクションゲームのボスは以下になります。
- イヌ(Dog) 一定時間ごとにプレイヤーに突進&ジャンプを行う
- クマ(Bear) 壁をよじ登る・ジャンプ・遠距離攻撃する敵
- ワシ(Eagle) 空中を移動して地上に攻撃する敵
- ペンギン(Penguin) 滑りながら攻撃・全方位シューティング攻撃の実装
- クラゲ(Jellyfish) プカプカ浮遊しながら弾幕を作る敵
- ワニ(Crocodile) 複数の遠距離攻撃パターンを実装
- キツネ(Fox) ジャンプ移動・狐火(炎の弾丸)を放出
- ライオン(Fox) 壁をバウンドしながら攻撃・HPが減ると行動パターンが変化
以上のような個性豊かなボスキャラを実装していきます。
Unityで2Dアクションゲームのボス戦を実装する
ボスとの戦闘は通常敵と区別がつくようにいくつかの演出を追加します。
過去に作成したスクリプトにボス戦用の修正を行う
まずはこれまで作ってきたスクリプトに修正を加え、ボス戦実装の準備を行っていきます。
EnemyBase.cs
戦闘開始時に専用BGM再生を行い、撃破時にパーティクル再生とステージクリアの呼び出しを行うための処理を追加します。
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 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; /// <summary> /// 全エネミー共通処理クラス /// </summary> public class EnemyBase : MonoBehaviour { // オブジェクト・コンポーネント [HideInInspector] public AreaManager areaManager; // エリアマネージャ protected Rigidbody2D rigidbody2D; // RigidBody2D protected SpriteRenderer spriteRenderer;// 敵スプライト protected Transform actorTransform; // 主人公(アクター)のTransform // 画像素材 public Sprite sprite_Defeat; // 被撃破時スプライト(あれば) // 各種変数 // 基礎データ(インスペクタから入力) [Header ("最大体力(初期体力)")] public int maxHP; [Header ("接触時アクターへのダメージ")] public int touchDamage; [Header ("ボス敵フラグ(ONでボス敵として扱う。1ステージに1体のみ)")] public bool isBoss; [Header ("ボス用被撃破パーティクルPrefab")] public GameObject bossDefeatParticlePrefab; // その他データ [HideInInspector] public int nowHP; // 残りHP [HideInInspector] public bool isVanishing; // 消滅中フラグ trueで消滅中である [HideInInspector] public bool isInvis; // 無敵モード [HideInInspector] public bool rightFacing; // 右向きフラグ(falseで左向き) // DoTween用 private Tween damageTween; // 被ダメージ時演出Tween // 定数定義 private readonly Color COL_DEFAULT = new Color (1.0f, 1.0f, 1.0f, 1.0f); // 通常時カラー private readonly Color COL_DAMAGED = new Color (1.0f, 0.1f, 0.1f, 1.0f); // 被ダメージ時カラー private const float KNOCKBACK_X = 1.8f; // 被ダメージ時ノックバック力(x方向) private const float KNOCKBACK_Y = 0.3f; // 被ダメージ時ノックバック力(y方向) // 初期化関数(AreaManager.csから呼出) public void Init (AreaManager _areaManager) { // 参照取得 areaManager = _areaManager; actorTransform = areaManager.stageManager.actorController.transform; rigidbody2D = GetComponent<Rigidbody2D> (); spriteRenderer = GetComponent<SpriteRenderer> (); // 変数初期化 rigidbody2D.freezeRotation = true; nowHP = maxHP; if (transform.localScale.x > 0.0f) rightFacing = true; // エリアがアクティブになるまで何も処理せず待機 gameObject.SetActive (false); } /// <summary> /// このモンスターの居るエリアにアクターが進入した時の処理(エリアアクティブ化時処理) /// </summary> public virtual void OnAreaActivated () { // このモンスターをアクティブ化 gameObject.SetActive (true); // ボス敵用処理 if (isBoss) { // BGM再生 areaManager.stageManager.PlayBossBGM (); } } /// <summary> /// ダメージを受ける際に呼び出される /// </summary> /// <param name="damage">ダメージ量</param> /// <returns>ダメージ成功フラグ trueで成功</returns> public bool Damaged (int damage) { // 消滅中なら無効 if (isVanishing) return false; // ダメージ処理 nowHP -= damage; if (nowHP <= 0) {// HP0の場合 // 被ダメージTween初期化 if (damageTween != null) damageTween.Kill (); damageTween = null; // 消滅中フラグをセット isVanishing = true; // 消滅中は物理演算なし rigidbody2D.velocity = Vector2.zero; rigidbody2D.bodyType = RigidbodyType2D.Kinematic; // 点滅後に消滅処理を呼び出す(DoTween使用) spriteRenderer.DOFade (0.0f, 0.15f) // 0.15秒*ループ回数分の再生時間 .SetEase (Ease.Linear) // 変化の仕方を指定 .SetLoops (7, LoopType.Yoyo) // 7回ループ再生(偶数回は逆再生) .OnComplete (Vanish); // 再生が終わったらVanish()を呼び出す設定 // 被撃破時スプライトがあれば表示 if (sprite_Defeat != null) spriteRenderer.sprite = sprite_Defeat; // その他撃破時処理 if (isBoss) {// ボス撃破時 // ボス撃破パーティクルを生成 var obj = Instantiate (bossDefeatParticlePrefab); obj.transform.position = transform.position; // ゲームクリア処理 areaManager.stageManager.StageClear (); } else {// ザコ撃破時 } } else {// まだHPが残っている場合 // 被ダメージTween初期化 if (damageTween != null) damageTween.Kill (); damageTween = null; // 被ダメージ演出再生 // (一瞬だけスプライトを赤色に変更する) if (!isInvis) { spriteRenderer.color = COL_DAMAGED; // 赤色に変更 damageTween = spriteRenderer.DOColor (COL_DEFAULT, 1.0f); // DoTweenで徐々に戻す } } return true; } /// <summary> /// エネミーが消滅する際に呼び出される /// </summary> private void Vanish () { // オブジェクト消滅 Destroy (gameObject); } /// <summary> /// アクターに接触ダメージを与える処理 /// </summary> public void BodyAttack (GameObject actorObj) { // 自身が消滅中なら無効 if (isVanishing) return; // アクターのコンポーネントを取得 ActorController actorCtrl = actorObj.GetComponent<ActorController> (); if (actorCtrl == null) return; // アクターに接触ダメージを与える actorCtrl.Damaged (touchDamage); } /// <summary> /// オブジェクトの向きを左右で決定する /// </summary> /// <param name="isRight">右向きフラグ</param> public void SetFacingRight (bool isRight) { if (!isRight) {// 左向き // スプライトを通常の向きで表示 spriteRenderer.flipX = false; // 右向きフラグoff rightFacing = false; } else {// 右向き // スプライトを左右反転した向きで表示 spriteRenderer.flipX = true; // 右向きフラグon rightFacing = true; } } } |
まだこの段階ではエラーが出るはずです。続いてStageManager.csを修正します。
StageManager.cs
ボス戦闘時に流れるBGMの設定を追加し、ステージクリア・ゲームオーバー時に呼び出す処理も形だけ追加しておきます。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; /// <summary> /// ステージマネージャクラス /// </summary> public class StageManager : MonoBehaviour { [HideInInspector] public ActorController actorController; // アクター制御クラス [HideInInspector] public CameraController cameraController; // カメラ制御クラス [Header ("初期エリアのAreaManager")] public AreaManager initArea; // ステージ内の最初のエリア(初期エリア) [Header ("ボス戦用BGMのAudioClip")] public AudioClip bossBGMClip; // ステージ内の全エリアの配列(Startで取得) private AreaManager[] inStageAreas; // Start void Start() { // 参照取得 actorController = GetComponentInChildren<ActorController> (); cameraController = GetComponentInChildren<CameraController> (); // ステージ内の全エリアを取得・初期化 inStageAreas = GetComponentsInChildren<AreaManager> (); foreach (var targetAreaManager in inStageAreas) targetAreaManager.Init (this); // 初期エリアをアクティブ化(その他のエリアは全て無効化) initArea.ActiveArea (); } /// <summary> /// ステージ内の全エリアを無効化する /// </summary> public void DeactivateAllAreas () { foreach (var targetAreaManager in inStageAreas) targetAreaManager.gameObject.SetActive (false); } /// <summary> /// ボス戦用BGMを再生する /// </summary> public void PlayBossBGM () { // BGMを変更する GetComponent<AudioSource> ().clip = bossBGMClip; GetComponent<AudioSource> ().Play (); } /// <summary> /// ステージクリア時処理 /// </summary> public void StageClear () { // ステージクリア処理 } /// <summary> /// ゲームオーバー処理 /// </summary> public void GameOver () { // ゲームオーバー処理 } } |
スクリプトを編集できたらStageManagerプレハブを編集し、bossBGMClipパラメータに対して適当なボス戦闘用音源ファイルをセットしましょう。
もちろんステージごとに異なるボスBGMを設定することも可能です。
ボス撃破パーティクルプレハブを作成
ボスを倒しても演出がザコを倒した時と同じでは少々味気ないです。
UnityのParticleSystemを使用し、ボス撃破時に光が周囲に飛び散るような演出を作成してみましょう。
ヒエラルキー画面で右クリックし、[Effects]→[Particle System]を選択してパーティクルオブジェクトを作成可能です。オブジェクト名はDefeatParticleとしました。
初期状態では小さく白い粒が上方向に登っているのが分かると思いますが、この粒1つ1つがパーティクルであり、これらの生成や速度等を制御できるのがパーティクルシステムです。
Inspectorから確認できるParticleSystemコンポーネントを編集することで設定変更が可能です。
上部では粒の速度や生存時間、色などの基本的な設定が行え、下部に連なっているModule(モジュール)を有効にして編集することでさらに生成頻度や出現位置も変更できるようになります。
以下、よく使う設定に絞って設定項目の解説を行っていきます。
自分で数値を変更して変化を確認すると良いでしょう。
Unity パーティクルシステム(Particle System)を解説
パーティクルの基本設定 項目一覧
どのようなパーティクルを作る場合でも恐らく必ず確認することになるパラメータが多いです。
Duration | パーティクル実行時間(秒) |
Looping | ループ設定(ONでループする) |
Start Lifetime | パーティクル内の各粒子の生存時間(秒) 入力欄右側のメニューから[Random Between Two Constants]を指定することで、乱数の幅を指定してのランダム数値にすることもできる。(他の数値入力系の設定でも同様) |
Start Speed | 各粒子の初期速度 |
Start Size | 各粒子の初期サイズ(1が基準) |
Start Rotation | 各粒子の初期角度(移動する方向ではない。0~360で指定) |
Start Color | 各粒子の初期表示色 |
Play on Awake | ONにするとシーン開始時またはオブジェクト生成時に自動的にパーティクルを再生開始する |
Stop Action | パーティクル再生完了時に行う処理。Destroyを指定するとそのパーティクルのオブジェクトごと消去する。 |
Emission (Module) パーティクルの発生頻度・生成量を設定
粒子の発生条件について設定します。
Rate over Time | 毎秒の粒子生成量 (0で時間経過による生成を行わない) |
Bursts | 特定のタイミングで一気に複数の粒子を生成する設定。 Time:生成タイミング(再生開始からの秒) Count:生成量 |
Shape (Module) パーティクルの進行方向を設定
粒子を発生させる範囲や粒子の進む方向などを設定します。
Shapeパラメータにて発生範囲の形状の種類を指定します。この設定によってその他の設定すべきパラメータが変化します。
例えばCircle(円形)を指定すると粒子は円の範囲内で生成されるようになり、その範囲をRadiusパラメータにて数値指定することになります。
Color over Lifetime (Module) パーティクルの寿命を設定
粒子の表示色を寿命までの時間によって変化させます。透明度(alpha)も変化可能です。
Colorパラメータ右側の矩形をクリックすると編集できます。左側のツマミ(キー)を編集すると再生開始時の色を、右側のツマミでは終了時の色を変更可能です。
上部では粒の速度や生存時間、色などの基本的な設定が行え、下部に連なっているModule(モジュール)を有効にして編集することでさらに生成頻度や出現位置も変更できるようになります。
(今回はこのModuleは使用しませんが、よく使う設定なので紹介します。)
Renderer (Module) パーティクルの表示・非表示の設定
パーティクル全体の表示設定を行います。
Materialパラメータからパーティクルに使用するマテリアル(素材データ)を変更できます。
パーティクルに任意の画像を表示させたい場合も画像データの直接指定は出来ないので、一度Materialを作成してここにセットする必要があります。
Unityパーティクルを放射状に表示させる ボス撃破用パーティクルを実装
Particle Systemの設定を変更し、ボス撃破時に再生するものとして使いやすい演出に仕上げていきましょう。
パーティクルの基本設定
パーティクルの速度や大きさ等を設定します。Start SpeedとStart Sizeの右側の↓を選んで”Random between two constants”を選べば2つの値を設定できるようになります。
StopActionにDestroyを指定するのを忘れないようにしましょう(そうでないと再生完了後もオブジェクトが残り続けます)。
Emissionの設定
自然生成のペースを時間経過と共に低下させながら、0.8秒経過のタイミングで大量の生成を1度だけ行います。
Rate Overtimeの右側の↓をクリックし、Curveを選択し、曲線の設定を行うことでゆるやかな値の変化を実現できます。
ちなみにサンプルゲームの方では以下のようなCurve設定になっています。
カーブの設定の流れは以下の動画のような手順です。
Shapeの設定
粒の生成範囲を円形(Circle)に設定します。
なお、TransformのRotation値が全て0でないと機能しないのでご注意ください。
Rendererの設定
Materialに今回使用するマテリアルをセットします。
サンプル用に既に用意しているAssets/Textures/Other/CircleMaterial.matを使用すると良いでしょう。
サンプルと全く同じでなくても大丈夫なので、ある程度納得いくものを作成できたらオブジェクトをプレハブ化しておきましょう。
プレハブ化したらScene上にあるDefeatParticleインスタンスは削除してOKです。
Unity 2D横スクロールアクションゲームのボス戦の作り方
ここからはついにボス戦の構築に入っていきます。
ボス敵1:イヌ(Dog) 一定時間ごとにプレイヤーに突進&ジャンプを行う
サンプル画像:Textures/Enemies/Boss/Dog1.png~Dog6.png
準備も整いましたのでいよいよボス敵の制作に入ります。
基本的な流れはザコ敵を作った時と同じですが、行動パターンをもう少し複雑に作り込みます。
また同じような処理でも細かな設計方法の違いがありますので、結構自由なコーディングでも作れることを確認してみましょう。
イヌは以下の行動パターンで設計します。
- 一定時間ごとに主人公の居る方向へ突進を行う
- 一定確率で突進時にジャンプする
全方位ショット攻撃用に青い弾丸オブジェクトを作成
ここまでエネミー弾丸を作成した時と同様の流れで、青色の弾丸オブジェクトEnemyShot_Blueを作成しましょう。
使用する画像はEnemy_Shot_Blue.pngです。
Boss_Penguinオブジェクト
以下は設定例です。シンプルな動きのボスではありますが、氷床ステージの効果によってアクターの動きが制限されているのでこのくらいが丁度良いかと思います。
氷のステージによく似合うボスが作成できました。
まとめ
ここまでで個性豊かなアクションを行う4体のボスを作成できました。
長くなってきたので一旦記事を分割し、次回残りのボスを制作していきます。
次の記事:
コメント