報酬
Coddyの「Unityゲーム:タワーディフェンス」コースのレッスン 13/25。
タワーが倒した敵はすべて、rewardを報酬として支払います。Enemyは、ベースに到達したことを通知するのと同じ方法で、静的イベントKilledを使って撃破を通知し、GameManagerがそれを受け取ってお金を加算します。
撃破報酬は一度だけ支払われなければなりません。Destroyを呼び出しても、オブジェクトはすぐには削除されません。フレームの終わりに削除されるため、それまではゲーム内に残っています。同じフレームに2発の弾が命中することがあり、2発目は体力が0で、まだそこにいる敵に当たります。体力が0以下になるたびにTakeDamageが撃破を通知すると、2発目でも報酬が支払われてしまいます。ダーツを使う風船ゲームにも同じ落とし穴がありますが、boolを使えば防げます。
public void Pop()
{
if (popped)
{
return;
}
popped = true;
Popped?.Invoke(this);
Destroy(gameObject);
}敵には追加のboolは必要ありません。体力ですでに死亡しているかどうかがわかるからです。体力が0以下の状態で呼び出されたTakeDamageには、もうすることがありません。
チャレンジ
中級敵を倒すたびに、その敵の報酬を獲得します。
Enemyにpublic static event Action<Enemy> Killed;を追加し、敵が破棄される直前にTakeDamage内でイベントを発生させます。- 倒したときに報酬が一度だけ支払われるよう、
TakeDamageの最初にif (health <= 0) return;を追加します。 GameManagerにpublic void Earn(int amount)(追加して表示する)を追加し、Enemy.Killedを購読してenemy.data.rewardを獲得するようにします。
「プレイ」を押すと、タワーが動くにつれて所持金が増えます。その後、「確認」を押します。
自分で試してみよう
using System;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour, IDamageable
{
public static readonly List<Enemy> All = new List<Enemy>();
public static event Action<Enemy> ReachedBase;
public EnemyData data;
public Transform[] waypoints;
private int next = 1;
private int health;
void Awake()
{
health = data.maxHealth;
}
void OnEnable()
{
All.Add(this);
}
void OnDisable()
{
All.Remove(this);
}
void Update()
{
Vector3 target = waypoints[next].position;
transform.position = Vector3.MoveTowards(transform.position, target, data.speed * Time.deltaTime);
if (transform.position == target)
{
next++;
if (next == waypoints.Length)
{
ReachedBase?.Invoke(this);
Destroy(gameObject);
}
}
}
public void TakeDamage(int amount)
{
health -= amount;
if (health <= 0)
{
Destroy(gameObject);
}
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
Unityゲーム:タワーディフェンスのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド