Menu
CoddyTech

Следующая волна

Урок 17 из 18 курса Игра в Unity: защита башен на Coddy.

Между волнами игрок строит, а обратный отсчёт показывает, сколько времени осталось. Игрок, который готов, может вызвать следующую волну раньше времени кнопкой. Перерыв — это цикл в корутине, который выдаёт null, поэтому он выполняется один раз за кадр: отсчитывает оставшееся время, показывает его и завершается, когда время истекает или когда кнопка запрашивает волну. Кнопка только устанавливает логическое значение, а цикл его проверяет:

while (left > 0f && !skipRequested)
{
    // показать оставшееся время в секундах, уменьшить счётчик, подождать один кадр
}
skipRequested = false;

Логическое значение снова устанавливается в false после использования, иначе каждый перерыв после первого сразу же завершался бы. Mathf.CeilToInt округляет вверх, поэтому при оставшихся 2.3 секунды отображается 3, а обратный отсчёт показывает 1 в течение всей последней секунды, а не 0. Обратный отсчёт — отдельная корутина, и yield return StartCoroutine(Countdown()); запускает её и ждёт завершения, прежде чем цикл волн продолжится.

На HUD также отображается номер волны. Спавнер знает его, а GameManager показывает, поэтому спавнер вызывает событие C#, WaveStarted, передавая волну и общее количество волн. В отличие от статических событий врагов, оно принадлежит одному спавнеру, и 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: защита башен