この記事はロックマン風2Dアクションゲームの作り方講座の第13回です。
11章と12章にてボス敵の作成とHPゲージの実装を行いました。
前回の記事:
今回はロックマンのゲーム性を高めている機能の一つである「倒した敵の武器を使えるようにする」機能を実装します。
プレイヤーに特殊武器を持たせ、ステージ攻略中に切り替えながら使用させることによってゲームの遊び方に幅を持たせていきます。
撃破したボスの特殊武器を使えるシステムの実装
プレイヤーキャラが様々な武器を切り替えて使用できるシステムをこれから実装していきます。仕様は以下のようなものになります。
- 初期武器+追加武器7種の計8種類の武器がある
- 装備中の武器はAキーまたはSキーで切り替えできる
- 追加武器は初期では使用できないが、0番目~7番目のボスを倒すとそれぞれ対応したものが解禁される
- 追加武器にはエネルギー残量が設定されており、エネルギー切れになるとその武器は使用できない(ステージを切り替えるとエネルギー回復)
ほか、初期武器にも共通して付与する仕様として連射速度の制限を実装予定です(攻撃した後、指定された時間の間は次の攻撃が出来ない)。
特殊ウェポン武器の種類一覧
ステージクリア後に手に入る特殊武器7種を以下のような内容で作成します。
(初期武器) | 作成済み |
Doggy(犬騎乗) | 攻撃はせず、犬に乗ったり降りたりします。犬に乗っている間はジャンプ力上昇 |
Tackle(タックル) | 前方に短い距離で瞬間移動しつつ無敵時間を発生させ、射程の短い弾を撃ちます。 |
Windblow(突風) | 前方に竜巻弾を発射し、当たった敵をノックバックさせます。(ボスにはノックバック無効) |
IceBall(雪玉) | 斜め上方向に弾を発射します。(弾は物理演算に従う) |
Lightning(稲妻) | 斜め上の離れた位置から真下に弾を発射します。 |
WaterRing(水の輪) | プレイヤーキャラの周囲にゆっくりした弾を複数発射します。 |
Laser(レーザー) | 一瞬で射程の端まで届く範囲攻撃を行います。 |
武器切り替え処理とエネルギーゲージを実装する
まずは武器の切り替え処理やエネルギー残量システムをまとめて実装していきます。各追加武器の実装はその後に行い、ステージクリア時の武器アンロック機能は次章で実装します。
ActorController.cs (一部省略)
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 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; /// <summary> /// アクター操作・制御クラス /// </summary> public class ActorController : MonoBehaviour { // オブジェクト・コンポーネント参照 private Rigidbody2D rigidbody2D; private SpriteRenderer spriteRenderer; private ActorGroundSensor groundSensor; // アクター接地判定クラス private ActorSprite actorSprite; // アクタースプライト設定クラス public CameraController cameraController; // カメラ制御クラス public Image hpGage; // HPゲージ public Image energyGage = null; // 武器エネルギーゲージ public Image energyGageIcon = null; // 武器エネルギーゲージアイコン // 設定項目 [Header ("true:足場が滑るモード")] public bool icyGroundMode; [Header ("各武器で使用するプレハブリスト(定義の順番に設定)")] public List<GameObject> weaponBulletPrefabs; [Header ("各武器のエネルギーゲージの画像")] public List<Sprite> weaponIconSprites; [Header ("各武器のエネルギーゲージの色")] public List<Color> weaponGageColors; [Header ("各武器の消費エネルギー量")] public List<int> weaponEnergyCosts; [Header ("各武器の連射間隔(秒)")] public List<float> weaponIntervals; // 体力変数 [HideInInspector] public int nowHP; // 現在HP [HideInInspector] public int maxHP; // 最大HP // 装備変数 [HideInInspector] public ActorWeaponType nowWeapon; private int[] weaponEnergies; // 武器の残りエネルギーデータ(それぞれ最大値がMaxEnergy) private float weaponRemainInterval; // 武器が次に発射可能になるまでの残り時間(秒) // 移動関連変数 [HideInInspector] public float xSpeed; // X方向移動速度 [HideInInspector] public bool rightFacing; // 向いている方向(true.右向き false:左向き) private float remainJumpTime; // 空中でのジャンプ入力残り受付時間 // その他変数 private float remainStuckTime; // 残り硬直時間(0以上だと行動できない) private float invincibleTime; // 残り無敵時間(秒) [HideInInspector] public bool isDefeat; // true:撃破された(ゲームオーバー) [HideInInspector] public bool inWaterMode; // true:水中モード(メソッドから変更) // 定数定義 private const int InitialHP = 20; // 初期HP(最大HP) private const int MaxEnergy = 20; // 武器エネルギーの最大値 private const float InvicibleTime = 2.0f; // 被ダメージ直後の無敵時間(秒) private const float StuckTime = 0.5f; // 被ダメージ直後の硬直時間(秒) private const float KnockBack_X = 2.5f; // 被ダメージ時ノックバック力(x方向) private const float WaterModeDecelerate_X = 0.8f;// 水中でのX方向速度倍率 private const float WaterModeDecelerate_Y = 0.92f;// 水中でのX方向速度倍率 // アクター装備定義 public enum ActorWeaponType { Normal, // (通常) Doggy, // 犬騎乗 Tackle, // タックル Windblow, // 突風 IceBall, // 雪玉 Lightning, // 稲妻 WaterRing, // 水の輪 Laser, // レーザー _Max, } // Start(オブジェクト有効化時に1度実行) void Start() { // コンポーネント参照取得 rigidbody2D = GetComponent<Rigidbody2D> (); spriteRenderer = GetComponent<SpriteRenderer> (); groundSensor = GetComponentInChildren<ActorGroundSensor> (); actorSprite = GetComponent<ActorSprite> (); // 配下コンポーネント初期化 actorSprite.Init (this); // カメラ初期位置 cameraController.SetPosition (transform.position); // 武器エネルギー初期化 weaponEnergies = new int[(int)ActorWeaponType._Max]; for (int i = 0; i < (int)ActorWeaponType._Max; i++) weaponEnergies[i] = MaxEnergy; ApplyWeaponChange (); // 初期装備を反映 // 変数初期化 nowWeapon = ActorWeaponType.Normal; // 初期装備 rightFacing = true; // 最初は右向き nowHP = maxHP = InitialHP; hpGage.fillAmount = 1.0f; // HPゲージの初期FillAmount } // Update(1フレームごとに1度ずつ実行) void Update() { // 撃破された後なら終了 if (isDefeat) return; // 無敵時間が残っているなら減少 if (invincibleTime > 0.0f) { invincibleTime -= Time.deltaTime; if (invincibleTime <= 0.0f) {// 無敵時間終了時処理 actorSprite.EndBlinking (); // 点滅終了 } } // 硬直時間処理 if (remainStuckTime > 0.0f) {// 硬直時間減少 remainStuckTime -= Time.deltaTime; if (remainStuckTime <= 0.0f) {// スタン時間終了時処理 actorSprite.stuckMode = false; } else return; } // 左右移動処理 MoveUpdate (); // ジャンプ入力処理 JumpUpdate (); // 武器切り替え処理 ChangeWeaponUpdate (); // 攻撃可能までの残り時間減少 if (weaponRemainInterval > 0.0f) weaponRemainInterval -= Time.deltaTime; // 攻撃入力処理 StartShotAction (); // 坂道で滑らなくする処理 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 && !icyGroundMode) { // Rigidbodyの機能のうち移動と回転を停止 rigidbody2D.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezePositionY | RigidbodyConstraints2D.FreezeRotation; } } // カメラに自身の座標を渡す cameraController.SetPosition (transform.position); } #region 移動関連 (省略) #endregion #region 装備関連 /// <summary> /// Updateから呼び出される武器切り替え処理 /// </summary> private void ChangeWeaponUpdate () { // 武器切り替え if (Input.GetKeyDown (KeyCode.A)) {// 1つ前に切り替え if (nowWeapon == ActorWeaponType.Normal) nowWeapon = ActorWeaponType._Max; nowWeapon--; // 武器変更を反映 ApplyWeaponChange (); } else if (Input.GetKeyDown (KeyCode.S)) {// 1つ次に切り替え nowWeapon++; if (nowWeapon == ActorWeaponType._Max) nowWeapon = ActorWeaponType.Normal; // 武器変更を反映 ApplyWeaponChange (); } } /// <summary> /// 特殊武器の変更を反映する /// </summary> public void ApplyWeaponChange () { // エネルギーゲージ表示(通常武器以外) if (nowWeapon == ActorWeaponType.Normal) energyGage.transform.parent.gameObject.SetActive (false); else energyGage.transform.parent.gameObject.SetActive (true); // ゲージの色を反映 energyGage.color = weaponGageColors[(int)nowWeapon]; // ゲージの量を反映 energyGage.fillAmount = (float)weaponEnergies[(int)nowWeapon] / MaxEnergy; // ゲージのアイコンを設定 energyGageIcon.sprite = weaponIconSprites[(int)nowWeapon]; } #endregion #region 戦闘関連 /// <summary> /// ダメージを受ける際に呼び出される /// </summary> /// <param name="damage">ダメージ量</param> public void Damaged (int damage) { // 撃破された後なら終了 if (isDefeat) return; // もし無敵時間中ならダメージ無効 if (invincibleTime > 0.0f) return; // ダメージ処理 nowHP -= damage; // HPゲージの表示を更新する float hpRatio = (float)nowHP / maxHP; hpGage.DOFillAmount (hpRatio, 0.5f); // HP0ならゲームオーバー処理 if (nowHP <= 0) { isDefeat = true; // 被撃破演出開始 actorSprite.StartDefeatAnim (); // 物理演算を停止 rigidbody2D.velocity = Vector2.zero; xSpeed = 0.0f; rigidbody2D.bodyType = RigidbodyType2D.Kinematic; // ゲームオーバー処理 GetComponentInParent<StageManager> ().GameOver (); return; } // スタン硬直 remainStuckTime = StuckTime; actorSprite.stuckMode = true; // ノックバック処理 // ノックバック力・方向決定 float knockBackPower = KnockBack_X; if (rightFacing) knockBackPower *= -1.0f; // ノックバック適用 xSpeed = knockBackPower; // 無敵時間発生 invincibleTime = InvicibleTime; if (invincibleTime > 0.0f) actorSprite.StartBlinking (); // 点滅開始 } /// <summary> /// 攻撃ボタン入力時処理 /// </summary> public void StartShotAction () { // 攻撃ボタンが入力されていないなら終了 if (!Input.GetKeyDown(KeyCode.Z)) return; // 武器エネルギーが足りないなら攻撃しない if (weaponEnergies[(int)nowWeapon] <= 0) return; // 攻撃可能までの時間が残っているなら終了 if (weaponRemainInterval > 0.0f) return; // 武器エネルギー減少 weaponEnergies[(int)nowWeapon] -= weaponEnergyCosts[(int)nowWeapon]; if (weaponEnergies[(int)nowWeapon] < 0) weaponEnergies[(int)nowWeapon] = 0; // 武器エネルギーゲージ表示更新 energyGage.fillAmount = (float)weaponEnergies[(int)nowWeapon] / MaxEnergy; // 次弾発射可能までの残り時間設定 weaponRemainInterval = weaponIntervals[(int)nowWeapon]; // 攻撃を発射 switch (nowWeapon) { case ActorWeaponType.Normal: // 通常攻撃 ShotAction_Normal (); break; case ActorWeaponType.Doggy: // 犬騎乗 ShotAction_Doggy (); break; case ActorWeaponType.Tackle: // タックル ShotAction_Tackle (); break; case ActorWeaponType.Windblow: // 突風 ShotAction_Windblow (); break; case ActorWeaponType.IceBall: // 雪玉 ShotAction_IceBall (); break; case ActorWeaponType.Lightning: // 稲妻 ShotAction_Lightning (); break; case ActorWeaponType.WaterRing: // 水の輪 ShotAction_WaterRing (); break; case ActorWeaponType.Laser: // レーザー ShotAction_Laser (); break; } } /// <summary> /// 射撃アクション:通常攻撃 /// </summary> private void ShotAction_Normal () { // 弾の方向を取得 float bulletAngle = 0.0f; // 右向き // アクターが左向きなら弾も左向きに進む if (!rightFacing) bulletAngle = 180.0f; // 弾丸オブジェクト生成・設定 GameObject obj = Instantiate (weaponBulletPrefabs[(int)ActorWeaponType.Normal], transform.position, Quaternion.identity); obj.GetComponent<ActorNormalShot> ().Init ( 12.0f, // 速度 bulletAngle, // 角度 1, // ダメージ量 5.0f, // 存在時間 nowWeapon); // 使用武器 } /// <summary> /// 射撃アクション:犬騎乗 /// </summary> private void ShotAction_Doggy () { } /// <summary> /// 射撃アクション:タックル /// </summary> private void ShotAction_Tackle () { } /// <summary> /// 射撃アクション:突風 /// </summary> private void ShotAction_Windblow () { } /// <summary> /// 射撃アクション:雪玉 /// </summary> private void ShotAction_IceBall () { } /// <summary> /// 射撃アクション:稲妻 /// </summary> private void ShotAction_Lightning () { } /// <summary> /// 射撃アクション:水の輪 /// </summary> private void ShotAction_WaterRing () { } /// <summary> /// 射撃アクション:レーザー /// </summary> private void ShotAction_Laser () { } #endregion } |
weaponBulletPrefabをList形式に変更し複数種の弾丸を扱えるようにしました。
武器の種類をenumで定義しています。
今後の拡張をスムーズにするため、各武器の使用時に呼び出すメソッドは予め作成しておきました。
それぞれの武器で生成するプレハブへの参照をリスト化し、1発あたり消費エネルギーの値などもパラメータとしてInspectorから設定できるようにしています。以下のスクリプトも編集し終えたらまとめて設定していきます。
ActorSprite.cs
装備中の武器に合わせてスプライトを変更可能にします。
またボス敵の時に使用した被撃破パーティクルの再生や、犬騎乗時のスプライトのセットまでできるようにしておきます。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; /// <summary> /// アクターのスプライトを設定するクラス /// </summary> public class ActorSprite : MonoBehaviour { private ActorController actorController; // アクター制御クラス private SpriteRenderer spriteRenderer; // アクターのSpriteRenderer public GameObject defeatParticlePrefab = null; // 被撃破パーティクルPrefab // 画像素材参照 public List<Sprite> walkAnimationRes; // 歩行アニメーション(装備別*コマ数) public List<Sprite> stuckSpriteRes; // スタンスプライト(装備別) public List<Sprite> swimAnimationRes; // 水泳アニメーション(コマ数) public Sprite doggySpriteRes; // 犬騎乗スプライト // 各種変数 private float walkAnimationTime; // 歩行アニメーション経過時間 private int walkAnimationFrame; // 歩行アニメーションの現在のコマ番号 private Tween blinkTween; // 点滅処理Tween public bool stuckMode; // スタン画像表示モード // 定数定義 private const int WalkAnimationNum = 3; // 歩行アニメーションの1種類あたりの枚数 private const float WalkAnimationSpan = 0.3f; // 歩行アニメーションのスプライト切り替え時間 // 初期化関数(ActorController.csから呼出) public void Init (ActorController _actorController) { // 参照取得 actorController = _actorController; spriteRenderer = actorController.GetComponent<SpriteRenderer> (); } // Update void Update () { // 被撃破中なら終了 if (actorController.isDefeat) return; // スタン画像表示モード中ならスタン画像を表示 if (stuckMode) { spriteRenderer.sprite = stuckSpriteRes[(int)actorController.nowWeapon]; return; } // 歩行アニメーション時間を経過(横移動している間のみ) if (Mathf.Abs (actorController.xSpeed) > 0.0f) walkAnimationTime += Time.deltaTime; // 歩行アニメーションコマ数を計算 if (walkAnimationTime >= WalkAnimationSpan) { walkAnimationTime -= WalkAnimationSpan; // コマ数を増加 walkAnimationFrame++; // コマ数が歩行アニメーション枚数を越えているなら0に戻す if (walkAnimationFrame >= WalkAnimationNum) walkAnimationFrame = 0; } // 歩行アニメーション更新 if (!actorController.inWaterMode) {// 地上 spriteRenderer.sprite = walkAnimationRes[(int)actorController.nowWeapon * WalkAnimationNum + walkAnimationFrame]; } else {// 水中 spriteRenderer.sprite = swimAnimationRes[walkAnimationFrame]; } } /// <summary> /// 点滅開始処理 /// </summary> public void StartBlinking () { // DoTweenを使った点滅処理 blinkTween = spriteRenderer.DOFade (0.0f, 0.15f) // 1回分の再生時間:0.15秒 .SetDelay (0.3f) // 0.3秒遅延 .SetEase (Ease.Linear) // 線形変化 .SetLoops (-1, LoopType.Yoyo); // 無限ループ再生(偶数回は逆再生) } /// <summary> /// 被撃破演出開始 /// </summary> public void StartDefeatAnim () { // 被撃破パーティクルを生成 var obj = Instantiate (defeatParticlePrefab); obj.transform.position = transform.position; // 被撃破スプライト表示 spriteRenderer.sprite = stuckSpriteRes[0]; // 点滅演出終了 if (blinkTween != null) blinkTween.Kill (); // スプライト非表示化アニメーション(DOTween) spriteRenderer.DOFade (0.0f, 2.0f); // 2.0秒かけてスプライトの非透明度を0.0fにする } /// <summary> /// 点滅終了処理 /// </summary> public void EndBlinking () { // DoTweenの点滅処理を終了させる if (blinkTween != null) { blinkTween.Kill (); // Tweenを終了 spriteRenderer.color = Color.white; // 色を元に戻す blinkTween = null; // Tween情報を初期化 } } } |
ActorNormalShot.cs
プレイヤーキャラ用の弾丸クラスも拡張します。いくつかの特殊武器はこのクラスをそのまま使う、あるいは継承したクラスを使用するので予め機能を増やしておきます。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// アクターの通常弾処理クラス /// </summary> public class ActorNormalShot : MonoBehaviour { // 各種変数 protected float speed; // 弾速 protected float angle; // 角度(0-360)0で右・90で上 protected int damage; // 命中時のダメージ protected float limitTime; // 存在時間(秒)この時間が過ぎると消滅 protected ActorController.ActorWeaponType useWeapon; // この弾を発射するのに使用した武器 /// <summary> /// 初期化関数(生成元から呼出) /// </summary> /// <param name="_speed">弾速</param> /// <param name="_angle">角度</param> /// <param name="_damage">命中時のダメージ</param> /// <param name="_limitTime">存在時間(秒)</param> /// <param name="_useWeapon">使用武器</param> public void Init (float _speed, float _angle, int _damage, float _limitTime, ActorController.ActorWeaponType _useWeapon) { // 変数取得 speed = _speed; angle = _angle; damage = _damage; limitTime = _limitTime; useWeapon = _useWeapon; } // Update void Update () { // 移動ベクトル計算(1フレーム分の進行方向と距離を取得) Vector3 vec = new Vector3 (speed * Time.deltaTime, 0.0f, 0.0f); vec = Quaternion.Euler (0, 0, angle) * vec; // ベクトル回転 // 移動ベクトルをもとに移動 transform.Translate (vec); // 消滅判定 limitTime -= Time.deltaTime; if (limitTime < 0.0f) {// 存在時間が0になったら消滅 Destroy (gameObject); } } /// <summary> /// (継承して使用)この弾が敵にダメージを与えた時の追加処理 /// </summary> protected virtual void OnDamagedEnemy (EnemyBase enemyBase) { } // 各トリガー呼び出し処理 // トリガー進入時に呼出 private void OnTriggerEnter2D (Collider2D collision) { string tag = collision.gameObject.tag; // 命中対象ごとの処理 if (tag == "Enemy") {// エネミーに命中 EnemyBase enemyBase = collision.gameObject.GetComponent<EnemyBase> (); if (enemyBase != null && !enemyBase.isInvis) { bool result = enemyBase.Damaged (damage); // ダメージ処理 // ダメージを与えられたなら弾オブジェクト削除 if (result) { // 追加処理 OnDamagedEnemy (enemyBase); // この弾を削除 Destroy (gameObject); } } } else if (tag == "Ground") {// 地面・壁に命中 Destroy (gameObject); } } } |
武器エネルギーゲージUI作成
StageManagerプレハブの編集画面に入り、武器エネルギーゲージのUIを準備しておきます。
Canvas以下にあるActorHPGageFrameオブジェクトを複製し、新しい方の名前をActorEnergyGageFrameに変更します。
HPゲージの右隣くらいに配置すると良いでしょう。(PosXが-400程度)
HPGageオブジェクトはEnergyGageと改名します(任意)。
ゲージの色およびIconの表示画像についてはスクリプトから制御するためここでは変更不要です。
Inspector設定
Actorオブジェクトに対して各種参照をセットしていきます。
まずは先ほど用意した武器エネルギーゲージUIの、ゲージ画像とゲージアイコン画像への参照をそれぞれセットします。
名前がweaponから始まる5つのリストは、全8種の武器の各データを入力・セットするパラメータです。まず武器数は8なのでリストの要素数には8を入力しておきます。各要素にセットする内容は後述します。
weaponBulletPrefabsリスト
各武器を発射する時に生成するプレハブへの参照をセットします。
以降のリストも含め、ActorControllerクラス内のActorWeaponTypeで定義されている武器の順番で内容を設定していきます。
現在は初期武器弾のプレハブしかないのでこれを格納します。
weaponIconSpritesリスト
各武器のアイコン画像をセットします。
基本的に弾の画像をセットすればOKで、Textures/Attacks/Actorフォルダ内に素材がまとまっています。
Doggy(犬騎乗)の部分のみTextures/Actors/Ride.pngを指定します。
weaponGageColorsリスト
武器ごとに設定できる武器エネルギーゲージの表示色です。
アルファ(A)値が0だと非表示になってしまうので1にすることを忘れないようにしましょう。色は適当で大丈夫です。
weaponEnergyCostsリスト
その武器を1回発射するごとに消費するエネルギーの量です。
後からバランス調整できるので適当な値を入力しましょう。ただし初期武器だけは消費エネルギーを0にしておくことを推奨します。
weaponIntervalsリスト
各武器の連射間隔です。1を入力すれば1秒ごとにしかその武器を発射できません。
これで一旦ActorController側への参照セットは終了です。この先弾丸プレハブを作成した時はここでの参照セットを追加します。
ActorSpriteコンポーネント
ここにはまずボス用に作成した被撃破パーティクルおよび犬に騎乗している時のプレイヤーキャラ画像の参照をセットしておきます。
そしてここからは装備中の武器別に歩行アニメーションおよびスタン画像の表示を分けるので、それぞれの装備用の画像をセットします。
これで一通り準備完了です。
ここまでの動作確認として、通常武器の連射間隔・武器切り替え・ゲージ表示等の機能が動いているかを見ておきましょう。
特殊武器1: 犬に騎乗 ライドアーマーなどの乗り物を簡易実装する方法
武器というイメージではないかもしれませんが、特殊武器の1つとして犬の上に乗って移動するモードに切り替える処理を実装します。
ロックマンでもライドアーマーや犬のラッシュなどアクション操作を助ける乗り物が登場するシリーズがありますよね。そんな乗り物を簡易的に実装するイメージです。
弾を発射しないのでプレハブを作成する必要はなく、スクリプトの編集のみで完了します。
まとめ
これで全8種の武器を実装完了しました。武器エネルギーの管理や連射速度の制限などを含め、よりアクションゲームらしいバランス調整が行えるようになったかと思います。
ついにゲーム開発も仕上げの段階になりました。タイトル画面から通しでプレイできるようにするためあと少し頑張りましょう!
次の記事:
コメント