報酬
Coddyの「Unityゲーム:タワーディフェンス」コースのレッスン 10/18。
タワーが倒した敵はすべて、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イベントKilled(Action<Enemy>)を宣言します。TakeDamageによって体力が0以下になったとき、破棄する直前に、その敵を渡してイベントを発生させます。- キル報酬は1回だけ支払われます。体力がすでに0以下の敵に対してTakeDamageが呼び出された場合、何もしません。
GameManager内に、所持金を加算して表示するpublic void Earn(int amount)を追加します。Enemy.KilledをReachedBaseと並べて購読し、倒した敵のrewardを獲得します。
Playを押して、タワーが動くにつれて所持金が増えるのを見てから、Checkを押します。
自分で試してみよう
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);
}
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。