基地にたどり着く
Coddyの「Unityゲーム:タワーディフェンス」コースのレッスン 3/18。
最後のウェイポイントまで歩いてきた敵は基地に到達しています。プレイヤーはライフを失い、敵は消えます。ライフはGameManagerが管理し、画面に表示します。敵が報告するためにGameManagerへの参照を持つ必要はありません。まもなく敵はプレハブから何体も生成されますが、プレハブからシーン内のオブジェクトを参照することはできないからです。
staticイベントを使えば、どちらの問題も解決できます。これは1体の敵ではなくEnemyクラスに属するため、GameManagerは一度だけ購読すれば、後から生成された敵も含めてすべての敵から通知を受け取れます。各敵は自分自身を引数としてイベントを発生させるので、リスナーはどの種類の敵が通過したかを読み取れます。プラットフォーマーのコインも同じ方法で通知します。
public class Coin : MonoBehaviour
{
public static event Action<Coin> Collected;
public int value = 1;
void OnTriggerEnter(Collider other)
{
Collected?.Invoke(this);
Destroy(gameObject);
}
}// ScoreBoard.cs
void OnEnable()
{
Coin.Collected += AddCoin;
}
void OnDisable()
{
Coin.Collected -= AddCoin;
}
void AddCoin(Coin coin)
{
score += coin.value;
}staticイベントはゲームが続く限り存続するため、-=はこれまで以上に重要です。破棄されたScoreBoardの購読が解除されずに残っていると、破棄済みのテキストに対して呼び出され、コードが失敗します。OnEnableとOnDisableは対になるため、各+=には対応する-=が必要です。
チャレンジ
簡単拠点にはライフが必要で、そこに到達した敵はライフを減らさなければなりません。
EnemyDataに、敵の種類ごとに拠点から奪うライフを表すpublic intdamageを追加します。Enemyに、敵を渡すpublic static eventReachedBase(Action<Enemy>)を宣言します。敵が最後のウェイポイントに到達したら、自身を渡してイベントを発生させ、そこで停止する代わりに敵を破棄します。GameManagerに、シリアライズされたintstartLives(20)と、最初はその値になるprivate intlivesを追加します。OnEnableでEnemy.ReachedBaseを購読し、OnDisableで購読を解除します。通り抜けた敵ごとに、そのアセットのdamageの値だけライフを減らします。- シリアライズされたTMP_Text
livesTextにライフをLives: 20のように表示し、開始時と変更のたびに更新します。
GameオブジェクトにはGameManagerがあり、InspectorでLivesTextが割り当てられ、両方のアセットのライフ消費量は1です。Playを押し、両方の敵が拠点に到達するまで待ってから、Checkを押します。
自分で試してみよう
using UnityEngine;
public class Enemy : MonoBehaviour
{
public EnemyData data;
public Transform[] waypoints;
private int next = 1;
private int health;
void Awake()
{
health = data.maxHealth;
}
void Update()
{
if (next >= waypoints.Length)
{
return;
}
Vector3 target = waypoints[next].position;
transform.position = Vector3.MoveTowards(transform.position, target, data.speed * Time.deltaTime);
if (transform.position == target)
{
next++;
}
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。