Menu
CoddyTech

ترقية

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

يستدعي زر «ترقية» في اللوحة UpgradeSelected. وتُخصم التكلفة عبر TrySpend في GameManager، لذا لا يغيّر نقص المال شيئًا. عند بلوغ المستوى الأقصى، لا يبقى شيء لشرائه: تعرض الإحصاءات القيم الحالية فقط، ولا يمكن التفاعل مع الزر.

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

challenge icon

التحدي

متوسط

رقِّ البرج المحدد من لوحته.

  1. اكتب public void UpgradeSelected(): عندما يكون المستوى أقل من maxLevel، إذا نجحت عملية الدفع باستخدام game.TrySpend(data.UpgradeCost(level))، فقم بترقية البرج وتحديث اللوحة.
  2. عند maxLevel، تعرض اللوحة Damage 4 وRange 5.5 في سطرين، وتعرض Max level، ولا يكون الزر المتسلسل upgradeButton قابلاً للتفاعل.
  3. في Update، أعد التنفيذ عندما تكون EventSystem.current.IsPointerOverGameObject() صحيحة.

اضغط «العب»، وابنِ برجًا، ثم انقر عليه ورقِّه مرتين: ستعرض اللوحة أنه بلغ المستوى الأقصى. ثم اضغط «تحقق».

جرّب بنفسك

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);
    [SerializeField] private GameObject towerPanel;
    [SerializeField] private TMP_Text towerNameText;
    [SerializeField] private TMP_Text towerStatsText;
    [SerializeField] private TMP_Text upgradeLabel;

    private Tower chosen;
    private Tower selected;

    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]);
        Select(null);
    }

    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))
        {
            Select(null);
            return;
        }

        Tower tower = hit.collider.GetComponentInParent<Tower>();
        if (tower != null)
        {
            Select(tower);
            return;
        }

        Select(null);
        if (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);
    }

    void Select(Tower tower)
    {
        selected = tower;
        towerPanel.SetActive(tower != null);
        if (tower != null)
        {
            ShowPanel();
        }
    }

    void ShowPanel()
    {
        TowerData data = selected.data;
        int level = selected.Level;
        towerNameText.text = data.towerName + " level " + level;
        towerStatsText.text = "Damage " + data.DamageAt(level) + " > " + data.DamageAt(level + 1)
            + "\nRange " + data.RangeAt(level) + " > " + data.RangeAt(level + 1);
        upgradeLabel.text = "Upgrade " + data.UpgradeCost(level);
    }
}

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

تدرّب بنفسك: Playground لـ Unity