Menu
CoddyTech

基地にたどり着く

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は対になるため、各+=には対応する-=が必要です。

challenge icon

チャレンジ

簡単

拠点にはライフが必要で、そこに到達した敵はライフを減らさなければなりません。

  1. EnemyDataに、敵の種類ごとに拠点から奪うライフを表すpublic int damageを追加します。
  2. Enemyに、敵を渡すpublic static event ReachedBase(Action<Enemy>)を宣言します。敵が最後のウェイポイントに到達したら、自身を渡してイベントを発生させ、そこで停止する代わりに敵を破棄します。
  3. GameManagerに、シリアライズされたint startLives(20)と、最初はその値になるprivate int livesを追加します。OnEnableでEnemy.ReachedBaseを購読し、OnDisableで購読を解除します。通り抜けた敵ごとに、そのアセットのdamageの値だけライフを減らします。
  4. シリアライズされた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++;
        }
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Unityゲーム:タワーディフェンスのすべてのレッスン