Menu
CoddyTech

Đếm ngược

Bài học 23 trên 25 trong khóa học Game Unity: thủ thành của Coddy.

Giữa các đợt, người chơi xây dựng, còn bộ đếm ngược cho biết còn bao lâu nữa. Người chơi đã sẵn sàng có thể nhấn nút để gọi đợt tiếp theo sớm hơn. Thời gian nghỉ là một vòng lặp trong coroutine, vòng lặp này trả về null, nên chạy một lần mỗi khung hình: vòng lặp đếm ngược thời gian, hiển thị thời gian còn lại và kết thúc khi hết giờ hoặc khi nút yêu cầu bắt đầu đợt tiếp theo. Nút chỉ đặt một giá trị bool, còn vòng lặp đọc giá trị đó:

while (left > 0f && !skipRequested)
{
    // Hiển thị số giây còn lại, đếm ngược, chờ một khung hình
}
skipRequested = false;

Giá trị bool trở về false sau khi được dùng, nếu không mọi lần nghỉ sau lần đầu tiên đều sẽ kết thúc ngay lập tức. Mathf.CeilToInt làm tròn lên, nên khi còn 2.3 giây, bộ đếm hiển thị 3. yield return StartCoroutine(Countdown()); chạy bộ đếm ngược và chờ cho đến khi bộ đếm kết thúc.

challenge icon

Thử thách

Khó

Đếm ngược trước mỗi đợt, một nút sẽ gọi đợt tiếp theo sớm hơn.

  1. Trong WaveSpawner, thêm countdownText (TMP_Text) và nextWaveButton (GameObject) được tuần tự hóa, private bool callNow; và public void CallNextWave() { callNow = true; }.
  2. Thay lệnh break bằng yield return StartCoroutine(Countdown());: hiển thị nút và trong khi vẫn còn thời gian, đồng thời callNow chưa bật, hiển thị Next wave in 8, làm tròn lên, ở mỗi khung hình.
  3. Sau đó đặt lại callNow thành false, xóa văn bản và ẩn nút.

Nhấn Chạy: nút Sóng tiếp theo bỏ qua thời gian chờ. Sau đó nhấn Kiểm tra.

Tự làm thử

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 = 8f;

    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");
    }
}

Tất cả bài học trong Game Unity: thủ thành

Tự luyện tập: Playground Unity