מכירה
שיעור 13 מתוך 18 בקורס משחק Unity: הגנת מגדלים של Coddy.
מכירת מגדל מחזירה חצי מהעלות שלו, כולל השדרוגים, כך שהעברת הגנה עולה משהו, אבל לא את מלוא הסכום. המגדל שומר סכום מצטבר של הכסף שהוצא עליו: המחיר שלו בעת הבנייה, בתוספת המחיר של כל שדרוג בזמן התשלום. ההחזר הוא חצי מהסכום הכולל הזה, וחלוקה של מספרים שלמים מעגלת אותו כלפי מטה. השכרת אופניים שומרת על אותו סוג של סכום מצטבר:
public void ExtendRide(int extraHours)
{
paid += extraHours * pricePerHour;
}
public int Deposit => paid / 4;מכירה הורסת את המגדל, והשדה tower של המשטח עדיין מצביע עליו. == של Unity מתייחס לאובייקט שהושמד כאילו הוא null, כך שהחל מהפריים הבא pad.tower == null הוא true, והמשטח שוב פנוי בלי צורך בקוד נוסף. הפאנל הוא עניין אחר: הוא עדיין מציג את המגדל שנמכר, ולחיצה על Upgrade תגיע לאובייקט שהושמד ותגרום ל-MissingReferenceException. מכירה לא בוחרת שום דבר, ולכן הפאנל מוסתר.
אתגר
בינוני- ב־
Tower, שמור משתנהintפרטי בשםspent: העלות של המגדל, המוגדרת ב־Start, בתוספת המחיר של כל שדרוג בעת רכישתו. הוסף אתpublic int SellValue => spent / 2;. - ב־
BuildManager, הצג אתSell 25, ערך המכירה של המגדל שנבחר, בתוךsellLabelמסוגTMP_Textשעבר סריאליזציה, בכל פעם שהתוכן של החלונית מתעדכן. - כתוב את
public void SellSelected(), שאותו מפעיל כפתור Sell: החזר את ערך המכירה באמצעות GameManager, השמד את המגדל ובטל את הבחירה.
לחץ על Play, ואז בנה, שדרג ומכור כמה מגדלים, ואז לחץ על Check.
נסו בעצמכם
using UnityEngine;
using UnityEngine.EventSystems;
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 Button upgradeButton;
[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 || EventSystem.current.IsPointerOverGameObject())
{
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;
if (level < data.maxLevel)
{
towerStatsText.text = "Damage " + data.DamageAt(level) + " > " + data.DamageAt(level + 1)
+ "\nRange " + data.RangeAt(level) + " > " + data.RangeAt(level + 1);
upgradeLabel.text = "Upgrade " + data.UpgradeCost(level);
upgradeButton.interactable = true;
}
else
{
towerStatsText.text = "Damage " + data.DamageAt(level) + "\nRange " + data.RangeAt(level);
upgradeLabel.text = "Max level";
upgradeButton.interactable = false;
}
}
public void UpgradeSelected()
{
if (selected.Level >= selected.data.maxLevel)
{
return;
}
if (game.TrySpend(selected.data.UpgradeCost(selected.Level)))
{
selected.Upgrade();
ShowPanel();
}
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.