ゲームオーバー作ったら、そらゲームクリアでしょう。今回はWaveをこなした時点でクリアとします。
目次
ゲームクリアの表示を作る
ここの表示は基本的にはクリアと同じものを作ります。違いとしてはボタンが不要です。押したら再スタートの機能があってもいいですけどね。
- PanelGameClearを作成する
- PanelGameOverを右クリック>Duplicate(複製)
- 名前を変更:PanelGameClear
- TextMeshProの変更
- テキストを変更:Game Clear!!
- テキストの色を変更:青
- ボタンを削除
テキストの色を変更する必要は無いんですが、ゲームオーバーと同じだと雰囲気が出ない気がするので・・・
クリアの処理を実装
敵が何らかでやられたことを知らせる処理を追加
クリア判定を行うために必要となる処理を先に追加します。その中の1つに、すべての敵を対処することが含まれます。敵は、
- ディフェンダーに倒される
- お城まで到達する
のいずれかで消費されます。このどちらかが行われたのを知るためにEnemyControllerを修正します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Cinemachine;
public class EnemyController : MonoBehaviour
{
private EnemyData enemyData; // 敵のデータ
private Castle targetCastle; // お城
private float hp;
private float power;
private float speed;
public static UnityEvent<EnemyController> OnAnyDestroyed = new UnityEvent<EnemyController>();
public void Initialize(EnemyData enemyData, LineRenderer lineRenderer, Castle targetCastle)
{
this.enemyData = enemyData;
hp = enemyData.maxHp;
power = enemyData.power;
speed = enemyData.speed;
GetComponent<LineMover>().SetSpeed(speed);
var spriteRenderer = GetComponent<SpriteRenderer>();
spriteRenderer.sprite = enemyData.enemySprite;
var lineMover = GetComponent<LineMover>();
lineMover.Initialize(0, speed, lineRenderer);
this.targetCastle = targetCastle;
lineMover.OnEndReached += (sender, e) =>
{
Debug.Log("お城に到着したよ!");
if (this.targetCastle != null)
{
this.targetCastle.TakeDamage(power);
var impulseSource = GetComponent<CinemachineImpulseSource>();
impulseSource.GenerateImpulse(0.1f);
}
OnAnyDestroyed.Invoke(this);
Destroy(gameObject);
};
}
public void TakeDamage(float damage)
{
hp -= damage;
Debug.Log("HP: " + hp + "/" + enemyData.maxHp);
if (hp <= 0)
{
OnAnyDestroyed.Invoke(this);
Destroy(gameObject);
}
}
}
内容的にはお城がやられたときとなんだか似てますが、必ずお城にダメージを与えているTakeDamageより後にOnAnyDestroyedを行うようにしてください。イベントが発生するタイミングはほんの一瞬ですが、順序が変わってしまうと、最後の1擊でお城が破壊されたにも関わらず、ゲームクリアの判定が勝ってしまう場合があります。ご注意ください。
クリアの判定について
今回制作しているタワーディフェンスで、クリアの判定はどの様に取ることができるでしょうか。
- すべての敵をしのぎ切った
- 倒すでも良い
- お城に突っ込んで消費したでも良い
- お城が無事
上記を満たすためには、Waveで登場する敵の数と、敵がなんらかの方法でやられたという情報を知る必要があります。クリアの表示処理も合わせると、次のようなプログラムになります。
public class GameManager : MonoBehaviour
{
[SerializeField] private GameObject panelGameOver;
[SerializeField] private GameObject panelGameClear;
[SerializeField] private WaveData waveData;
private int totalEnemyCount = 0;
private int currentEnemyCount = 0;
private void Start()
{
panelGameOver.SetActive(false);
panelGameClear.SetActive(false);
// waveデータに含まれる敵の数を調べる
foreach (var enemyData in waveData.enemyDataList)
{
if (enemyData != null)
{
totalEnemyCount += 1;
}
}
// 敵がいなくなったら
EnemyController.OnAnyDestroyed.AddListener((enemy) =>
{
// カウントアップして
currentEnemyCount += 1;
// すべての敵を倒しつつ、ゲームオーバーになってなければ
if (totalEnemyCount <= currentEnemyCount && panelGameOver.activeSelf == false)
{
// クリア
panelGameClear.SetActive(true);
}
});
}
}
コメント
コメント一覧 (1件)
[…] TD-ゲームクリアの処理を作る part13 […]