Menu
CoddyTech

Jual

Pelajaran 19 dari 25 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

Jual menara seharga setengah dari biaya pembeliannya.

  1. Di Tower, pertahankan private int spent;: data.cost di Start, ditambah harga setiap peningkatan di Upgrade(). Tambahkan public int SellValue => spent / 2;.
  2. Di BuildManager, tampilkan Sell 25 (nilai jual) dalam TMP_Text berserialisasi sellLabel saat panel diisi.
  3. Tulis public void SellSelected(): kembalikan uang sebesar nilai jual, hancurkan menara, lalu jangan pilih apa pun.

Tekan tombol “Main”, lalu bangun, tingkatkan, dan jual menara. Setelah itu, tekan tombol “Periksa”.

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

Semua pelajaran di Game Unity: Tower Defense

Latihan sendiri: Playground Unity