Menu
CoddyTech
flag Ar iconالعربيةdown icon

الترقية

الدرس 12 من 18 في دورة لعبة Unity: الدفاع عن الأبراج على Coddy.

يؤدي النقر على برج إلى فتح لوحة تعرض مستواه وزر ترقية. يضيف كل مستوى إلى ضرر البرج ومداه، وتكلف كل ترقية أكثر من سابقتها. تتبع المستويات قاعدة، لذا يحتفظ الأصل بالقاعدة بدلًا من قائمة أرقام: الإحصاءات عند المستوى 1، وما يضيفه كل مستوى، وسعر الترقية. تحسب الطرق الموجودة في ScriptableObject بقية القيم، لذا تحصل كل شيفرة تطلبها على الإجابة نفسها. محصول في لعبة مزرعة:

public int YieldAt(int level)
{
    return baseYield + yieldPerLevel * (level - 1);
}

يحتفظ البرج بقيمة level الخاصة به فقط، وتعرض اللوحة أرقام المستوى التالي بجوار الأرقام الحالية، ليرى اللاعب ما الذي يشتريه بالمال. يصيب النقر على برج أحد أجزائه، القاعدة أو الرأس، وهما ابنان للبرج، لذا يعثر hit.collider.GetComponentInParent<Tower>() على البرج الذي ينتميان إليه: يبحث في الكائن الذي أصابه النقر، ثم يصعد عبر آبائه.

اللوحة واجهة مستخدم فوق العرض ثلاثي الأبعاد، والنقر على زر الترقية فيها هو أيضًا ضغطة زر بالماوس يراها BuildManager. يمر شعاعه عبر الزر إلى الأرض خلفه، ويغلق BuildManager اللوحة قبل تحرير الزر. تكون EventSystem.current.IsPointerOverGameObject() صحيحة ما دام المؤشر فوق واجهة المستخدم، لذا يعود BuildManager مبكرًا ويترك تلك النقرات للأزرار.

challenge icon

التحدي

متوسط
  1. في TowerData، أضف الأعداد الصحيحة العامة maxLevel وupgradeCost وdamagePerLevel، والعائم العام rangePerLevel. أضف int DamageAt(int level) وfloat RangeAt(int level): المستوى 1 له مقدار الضرر والمدى الخاصان بالأصل، وكل مستوى بعده يضيف المقدار لكل مستوى. أضف int UpgradeCost(int level)، وهو تكلفة الانتقال من ذلك المستوى إلى المستوى التالي: upgradeCost مضروبًا في المستوى.
  2. في Tower، احتفظ بمتغير عدد صحيح خاص level يبدأ بقيمة 1، ويمكن قراءة قيمته باستخدام public int Level => level;. أطلق النار باستخدام DamageAt(level) واستهدف ضمن RangeAt(level). أضف public void Upgrade()، الذي يزيد المستوى بمقدار 1.
  3. في BuildManager، يؤدي النقر على برج إلى تحديده، والنقر على أي شيء آخر إلى إلغاء التحديد (يؤدي النقر على منصة فارغة إلى البناء عليها). لا تظهر towerPanel المُسلسلة إلا عند تحديد برج، وتعرض Arrow level 1 في towerNameText، وDamage 2 > 3 وRange 4.5 > 5 على سطرين في towerStatsText، وUpgrade 40 في upgradeLabel. عند بلوغ maxLevel، تعرض الإحصائيات القيم الحالية فقط، ويكون النص Max level ويكون upgradeButton غير قابل للتفاعل.
  4. اكتب public void UpgradeSelected()، الذي يستدعيه زر الترقية: دون بلوغ المستوى الأعلى، عندما يتمكن GameManager من دفع تكلفة الترقية، قم بترقية البرج وتحديث اللوحة. تجاهل النقرات فوق واجهة المستخدم في Update.

اضغط على Play، وابنِ برجًا، ثم انقر عليه ورقِّه، وبعد ذلك اضغط على Check.

جرّب بنفسك

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using TMPro;

public class BuildManager : MonoBehaviour
{
    [SerializeField] private GameManager game;
    [SerializeField] private Tower[] shop;
    [SerializeField] private Button[] shopButtons;
    [SerializeField] private Color chosenColor = new Color(1f, 0.85f, 0.3f);

    private Tower chosen;

    void Start()
    {
        for (int i = 0; i < shop.Length; i++)
        {
            Tower prefab = shop[i];
            shopButtons[i].GetComponentInChildren<TMP_Text>().text = prefab.data.towerName + "\n" + prefab.data.cost;
            shopButtons[i].onClick.AddListener(() => Choose(prefab));
        }
        Choose(shop[0]);
    }

    void Choose(Tower prefab)
    {
        chosen = prefab;
        for (int i = 0; i < shop.Length; i++)
        {
            shopButtons[i].image.color = shop[i] == chosen ? chosenColor : Color.white;
        }
    }

    void Update()
    {
        if (!Mouse.current.leftButton.wasPressedThisFrame)
        {
            return;
        }

        Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
        if (Physics.Raycast(ray, out RaycastHit hit) && hit.collider.TryGetComponent(out BuildPad pad))
        {
            Build(pad);
        }
    }

    void Build(BuildPad pad)
    {
        if (pad.tower != null)
        {
            return;
        }

        if (!game.TrySpend(chosen.data.cost))
        {
            Debug.Log("Not enough money");
            return;
        }

        pad.tower = Instantiate(chosen, pad.transform.position, Quaternion.identity);
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس لعبة Unity: الدفاع عن الأبراج