הגל הבא
שיעור 17 מתוך 18 בקורס משחק Unity: הגנת מגדלים של Coddy.
בין הגלים השחקן בונה, וספירה לאחור מציגה כמה זמן נותר. שחקן שמוכן יכול להזניק את הגל הבא מוקדם באמצעות כפתור. ההפסקה היא לולאה בקורוטינה שמחזירה null, ולכן היא רצה פעם אחת בכל פריים: היא סופרת לאחור את הזמן שנותר, מציגה אותו ומסתיימת כשהזמן נגמר או כשהכפתור ביקש להזניק את הגל. הכפתור רק מגדיר ערך בוליאני, והלולאה קוראת אותו:
while (left > 0f && !skipRequested)
{
// הצג את מספר השניות שנותרו, בצע ספירה לאחור, המתן לפריים אחד
}
skipRequested = false;הערך הבוליאני מוגדר בחזרה ל-false אחרי השימוש בו, אחרת כל הפסקה אחרי הראשונה הייתה מסתיימת מיד. Mathf.CeilToInt מעגל כלפי מעלה, כך שכשנותרו 2.3 שניות מוצג 3, והספירה לאחור מציגה 1 לאורך כל השנייה האחרונה במקום 0. הספירה לאחור היא קורוטינה בפני עצמה, ו-yield return StartCoroutine(Countdown()); מפעיל אותה וממתין לסיומה לפני שלולאת הגלים ממשיכה.
ממשק המשתמש (HUD) מציג גם את מספר הגל. ה-spawner יודע אותו, ו-GameManager מציג אותו, ולכן ה-spawner מפעיל אירוע C#, WaveStarted, עם הגל ומספר הגלים. בניגוד לאירועים הסטטיים של האויבים, האירוע הזה שייך ל-spawner היחיד, ו-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");
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.