اجعله خاصًا بك
الدرس 18 من 18 في دورة لعبة Unity: الدفاع عن الأبراج على Coddy.
تحتاج اللعبة إلى نهاية. تخسر عندما تصل الأرواح إلى 0، وتفوز عندما تُرسل كل الموجات ولا يبقى أي عدو على اللوحة. يعرف المُرسِل متى تخرج الموجة الأخيرة، ويعرف Enemy.All عدد الأعداء المتبقين، لذا ينتظر المُرسِل حتى تصبح اللوحة خالية، ثم يطلق حدثًا يستمع إليه GameManager. تنتظر coroutine شرطًا باستخدام WaitUntil، الذي يتحقق من lambda مرة واحدة في كل إطار. غرفة أحجية تفتح مخرجها عندما تكون كل المفاتيح في وضع التشغيل:
yield return new WaitUntil(() => switchesOn == switches.Length);
exit.SetActive(true);تعرض كل نهاية EndPanel مع رسالة، وتوقف اللعبة باستخدام Time.timeScale = 0. لا تنخفض الأرواح أبدًا عن 0: فالدبابة التي تتلقى ضررًا بمقدار 2 عندما يتبقى 1 ستتجاوز فحص القيمة 0 تمامًا، لذا تحافظ Mathf.Max على الأرواح عند 0 أو أكثر.
يعيد زر «العب مجددًا» تحميل المشهد. إن Time.timeScale ليس جزءًا من المشهد، ويحتفظ بقيمته عند التحميل، لذا ستبدأ اللعبة مجمدة إذا كانت متوقفة عند 0: أعد ضبطه إلى 1 قبل التحميل.
بعد ذلك، اجعل اللعبة تعبّر عنك. كل ما يوازنها موجود في Inspector:
- GameManager الخاص باللعبة:
startMoney(150) وstartLives(20). wavesالخاصة بـ Spawner: ثمانية صفوف تتضمن العدو والعدد والتباعد، وtimeBetweenWaves(8).- أصول EnemyData: السرعة والصحة والمكافأة وعدد الأرواح التي يخصمها كل نوع. لدى Boss مقدار صحة يساوي 450 ويخصم 10 أرواح.
- أصول TowerData: التكلفة والضرر والمدى ومعدل الإطلاق وأرقام الترقية، وضرر الرذاذ لدى Cannon، والإبطاء لدى برج Frost.
يمكن التغلب على الأرقام الافتراضية باستخدام دفاع متنوع عند منعطفات المسار، مع ترقية الأبراج كلما توفرت الأموال؛ فلن تصمد بضعة أبراج من نوع واحد. غيّر رقمًا واحدًا في كل مرة، والعب لتشعر بتأثيره.
التحدي
صعب- في
WaveSpawner، أضفpublic event Action AllWavesCleared. بعد إرسال الموجة الأخيرة، انتظر حتى يصبحEnemy.Allفارغًا، ثم أطلق الحدث. - في
GameManager، أضف الحقلين المتسلسلينendPanel(من نوع GameObject) وendText(من نوع TMP_Text). لا تنخفض الأرواح أبدًا عن 0، وعندما تصل إلى 0 تنتهي اللعبة برسالةGame Over. عندما تُصفّى كل الموجات مع بقاء أرواح، تنتهي اللعبة برسالةYou Win!. عند انتهاء اللعبة، اعرض اللوحة مع الرسالة واضبطTime.timeScaleعلى 0. - اكتب
public void PlayAgain()، الذي يستدعيه زر اللوحة: أعد الوقت إلى وضعه الطبيعي، وحمّل المشهد النشط مرة أخرى.
اضغط Play ودافع عن القاعدة خلال الموجات الثماني كلها، ثم اضغط Check. بعد ذلك، اضبط اللعبة في Inspector والعب بالطريقة التي تناسبك.
جرّب بنفسك
using UnityEngine;
using TMPro;
public class GameManager : MonoBehaviour
{
[SerializeField] private int startMoney = 100;
[SerializeField] private int startLives = 20;
[SerializeField] private WaveSpawner spawner;
[SerializeField] private TMP_Text moneyText;
[SerializeField] private TMP_Text livesText;
[SerializeField] private TMP_Text waveText;
private int money;
private int lives;
void OnEnable()
{
Enemy.ReachedBase += OnReachedBase;
Enemy.Killed += OnKilled;
spawner.WaveStarted += ShowWave;
}
void OnDisable()
{
Enemy.ReachedBase -= OnReachedBase;
Enemy.Killed -= OnKilled;
spawner.WaveStarted -= ShowWave;
}
void Start()
{
money = startMoney;
lives = startLives;
ShowMoney();
ShowLives();
}
public bool TrySpend(int amount)
{
if (amount > money)
{
return false;
}
money -= amount;
ShowMoney();
return true;
}
public void Earn(int amount)
{
money += amount;
ShowMoney();
}
void OnKilled(Enemy enemy)
{
Earn(enemy.data.reward);
}
void OnReachedBase(Enemy enemy)
{
lives -= enemy.data.damage;
ShowLives();
}
void ShowMoney()
{
moneyText.text = "Money: " + money;
}
void ShowLives()
{
livesText.text = "Lives: " + lives;
}
void ShowWave(int wave, int total)
{
waveText.text = "Wave " + wave + "/" + total;
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.