Menu
CoddyTech

שדרוג

שיעור 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() מחזיר true כשהמצביע נמצא מעל ממשק המשתמש, ולכן BuildManager חוזר מיד ומשאיר את הלחיצות האלה לכפתורים.

challenge icon

אתגר

בינוני
  1. ב־TowerData, הוסף את המשתנים הציבוריים מסוג int maxLevel, upgradeCost ו־damagePerLevel, ואת המשתנה הציבורי מסוג float rangePerLevel. הוסף את int DamageAt(int level) ואת float RangeAt(int level): ברמה 1 נעשה שימוש בנזק ובטווח המקוריים של הנכס, ובכל רמה מעליה מתווסף הערך לכל רמה. הוסף את int UpgradeCost(int level), המחיר של מעבר מהרמה הזו לבאה אחריה: upgradeCost כפול הרמה.
  2. ב־Tower, שמור משתנה פרטי מסוג int בשם 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(), שאותו מפעיל כפתור Upgrade: מתחת לרמה המרבית, אם 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: הגנת מגדלים