Menu
CoddyTech

Vendi

Lezione 19 di 25 del corso Gioco Unity: Tower Defense di Coddy.

Vendendo una torre si recupera la metà di quanto è costata, potenziamenti inclusi, quindi spostare una difesa ha un costo, ma non si perde tutto. La torre tiene un totale aggiornato del denaro speso per essa: il suo prezzo al momento della costruzione, più il prezzo di ogni potenziamento man mano che viene pagato. Il rimborso è la metà di quel totale e la divisione intera lo arrotonda per difetto. Anche un noleggio di biciclette tiene lo stesso tipo di totale:

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

public int Deposit => paid / 4;

Vendere distrugge la torre e il campo tower della piazzola continua a puntare a essa. Unity tratta un oggetto distrutto come null con ==, quindi dal frame successivo pad.tower == null è true e la piazzola è di nuovo libera senza codice aggiuntivo. Il pannello è un'altra questione: continua a mostrare la torre venduta e un clic su Upgrade raggiungerebbe un oggetto distrutto e genererebbe una MissingReferenceException. La vendita non seleziona nulla, quindi il pannello si nasconde.

challenge icon

Sfida

Medio

Vendi una torre per metà del suo costo.

  1. In Tower, mantieni private int spent;: data.cost in Start, più il costo di ogni potenziamento in Upgrade(). Aggiungi public int SellValue => spent / 2;.
  2. In BuildManager, quando si riempie il pannello, mostra Sell 25 (il valore di vendita) in un TMP_Text serializzato sellLabel.
  3. Scrivi public void SellSelected(): recupera il valore di vendita, distruggi la torre e non selezionare nulla.

Premi «Gioca», poi costruisci, potenzia e vendi una torre. Quindi premi «Verifica».

Provalo tu

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

Tutte le lezioni di Gioco Unity: Tower Defense

Esercitati da solo: Playground Unity