Menu
CoddyTech

Jual

Pelajaran 13 dari 18 dalam kursus Game Unity: Tower Defense di Coddy.

Menjual tower mengembalikan setengah dari biayanya, termasuk biaya upgrade, jadi memindahkan pertahanan membutuhkan biaya, tetapi tidak seluruhnya. Tower menyimpan total uang yang telah dikeluarkan untuknya: harganya saat dibangun, ditambah harga setiap upgrade saat dibayar. Pengembalian dana adalah setengah dari total tersebut, dan pembagian bilangan bulat membulatkannya ke bawah. Penyewaan sepeda menyimpan total dengan cara yang sama:

public void ExtendRide(int extraHours)
{
    paid += extraHours * pricePerHour;
}

public int Deposit => paid / 4;

Menjual akan menghancurkan tower, dan field tower pada pad masih menunjuk ke sana. == milik Unity menganggap object yang sudah dihancurkan sebagai null, jadi mulai frame berikutnya pad.tower == null bernilai true, dan pad kembali kosong tanpa kode tambahan. Panelnya berbeda: panel masih menampilkan tower yang sudah dijual, dan klik Upgrade akan mengakses object yang sudah dihancurkan lalu memunculkan MissingReferenceException. Setelah penjualan, tidak ada yang dipilih, sehingga panel tersembunyi.

challenge icon

Tantangan

Sedang
  1. Di Tower, simpan int privat spent: cost tower yang ditetapkan di Start, ditambah harga setiap upgrade saat dibeli. Tambahkan public int SellValue => spent / 2;.
  2. Di BuildManager, tampilkan Sell 25, nilai jual tower yang dipilih, dalam TMP_Text terserialisasi sellLabel setiap kali panel diisi.
  3. Tulis public void SellSelected(), yang dipanggil oleh tombol Sell: kembalikan nilai jual melalui GameManager, hancurkan tower, lalu jangan pilih apa pun.

Tekan Play, lalu bangun, upgrade, dan jual beberapa tower, kemudian tekan Check.

Coba sendiri

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();
        }
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Game Unity: Tower Defense