Menu
CoddyTech

次のウェーブ

Coddyの「Unityゲーム:タワーディフェンス」コースのレッスン 17/18。

ウェーブの合間にプレイヤーは建築を行い、カウントダウンで残り時間が表示されます。準備ができたプレイヤーは、ボタンを押して次のウェーブを早めに開始できます。休憩は、null を返すコルーチン内のループなので、フレームごとに1回実行されます。残り時間をカウントダウンして表示し、時間切れになるか、ボタンでウェーブ開始が要求されると終了します。ボタンは bool を設定するだけで、ループがそれを読み取ります:

while (left > 0f && !skipRequested)
{
    // 残り秒数を表示し、カウントダウンして、1フレーム待つ
}
skipRequested = false;

bool は使用後に false に戻します。そうしないと、最初の休憩以降はすぐに終了してしまいます。Mathf.CeilToInt は切り上げるので、残り時間が2.3秒なら3と表示され、カウントダウンは最後の1秒間ずっと0ではなく1を表示します。カウントダウン自体もコルーチンであり、yield return StartCoroutine(Countdown()); はそれを実行し、完了するまで待ってからウェーブループを続行します。

HUDにはウェーブ番号も表示されます。Spawnerはその番号を把握しており、GameManagerが表示するため、Spawnerはウェーブ番号とウェーブ数を含むC#イベントWaveStartedを発行します。敵の静的イベントとは異なり、このイベントは1つのSpawnerに属し、GameManagerは自身のspawnerフィールドを通じて登録します。

challenge icon

チャレンジ

難しい
  1. WaveSpawner に、シリアライズ対象のフィールド countdownText(TMP_Text)と nextWaveButton(GameObject)、およびボタンから呼び出してウェーブをすぐに開始するよう要求する public void CallNextWave() を追加します。
  2. 各ウェーブの前の待機をカウントダウンに置き換え、yield return StartCoroutine(Countdown()); で実行します。実行中はボタンが表示され、テキストには残り秒数を切り上げた Next wave in 8 のような内容が表示されます。時間切れになるかボタンがクリックされると終了し、その後テキストは空になり、ボタンは非表示になります。
  3. public event Action<int, int> WaveStarted を追加し、ウェーブ開始時にウェーブ番号(1から)とウェーブ数を渡してイベントを発生させます。
  4. GameManager に、シリアライズ対象のフィールド spawner(WaveSpawner)と waveText(TMP_Text)を追加し、WaveStarted を購読して、Wave 1/8 を表示します。

HUD には WaveText、CountdownText、NextWaveButton があります。Play を押してビルドし、最初のウェーブを早めに開始してから、Check を押してください。

自分で試してみよう

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WaveSpawner : MonoBehaviour
{
    [SerializeField] private List<Wave> waves = new List<Wave>();
    [SerializeField] private Transform[] waypoints;
    [SerializeField] private float timeBetweenWaves = 5f;

    void Start()
    {
        StartCoroutine(RunWaves());
    }

    IEnumerator RunWaves()
    {
        for (int i = 0; i < waves.Count; i++)
        {
            yield return new WaitForSeconds(timeBetweenWaves);
            Debug.Log("Wave " + (i + 1));
            Wave wave = waves[i];
            for (int n = 0; n < wave.count; n++)
            {
                Enemy enemy = Instantiate(wave.enemy, waypoints[0].position, Quaternion.identity);
                enemy.waypoints = waypoints;
                yield return new WaitForSeconds(wave.spacing);
            }
        }
        Debug.Log("All waves sent");
    }
}
quiz icon腕試し

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

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