Следующая волна
Урок 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.
Задание
Сложно- В
WaveSpawnerдобавь сериализованные поляcountdownText(тип TMP_Text) иnextWaveButton(тип GameObject), а такжеpublic void CallNextWave(), который кнопка вызывает, чтобы запросить немедленный запуск волны. - Замени ожидание перед каждой волной обратным отсчётом, запущенным с помощью
yield return StartCoroutine(Countdown());. Пока он выполняется, кнопка отображается, а текст показываетNext wave in 8— количество оставшихся секунд, округлённое вверх. Отсчёт завершается, когда время истекает или когда нажата кнопка; после этого текст очищается, а кнопка скрывается. - Добавь
public event Action<int, int> WaveStarted, которое вызывается при начале волны с её номером (начиная с 1) и общим количеством волн. - В
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");
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.