Menu
CoddyTech

Verkaufen

Lektion 19 von 25 im Kurs Unity-Spiel: Tower Defense von Coddy.

Beim Verkauf eines Turms erhältst du die Hälfte seiner Kosten zurück, einschließlich der Upgrades. Eine Verteidigung zu versetzen kostet also etwas, aber nicht alles. Der Turm führt eine laufende Summe des für ihn ausgegebenen Geldes: seinen Preis beim Bau plus den Preis jedes Upgrades, sobald es bezahlt wird. Die Rückerstattung beträgt die Hälfte dieser Summe, und eine Ganzzahldivision rundet sie ab. Bei einer Fahrradvermietung wird dieselbe Art von Summe geführt:

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

public int Deposit => paid / 4;

Beim Verkauf wird der Turm zerstört, und das Feld tower des Pads verweist weiterhin auf ihn. Unity behandelt ein zerstörtes Objekt mit == als null, daher ist ab dem nächsten Frame pad.tower == null wahr und das Pad ist ohne zusätzlichen Code wieder frei. Beim Panel ist das anders: Es zeigt weiterhin den verkauften Turm an, und ein Klick auf Upgrade würde ein zerstörtes Objekt erreichen und eine MissingReferenceException auslösen. Beim Verkauf wird nichts ausgewählt, wodurch das Panel ausgeblendet wird.

challenge icon

Aufgabe

Mittel

Verkaufe einen Turm für die Hälfte seiner Kosten.

  1. Behalte in Tower private int spent; bei: data.cost in Start sowie den Preis jedes Upgrades in Upgrade(). Füge public int SellValue => spent / 2; hinzu.
  2. Zeige in BuildManager beim Füllen des Panels Sell 25 (den Verkaufserlös) in einem serialisierten TMP_Text sellLabel an.
  3. Schreibe public void SellSelected(): Erstatte den Verkaufserlös, zerstöre den Turm und wähle nichts aus.

Drücke „Spielen“, baue dann einen Turm, verbessere ihn und verkaufe ihn. Drücke anschließend „Prüfen“.

Probier es selbst

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

Alle Lektionen in Unity-Spiel: Tower Defense

Übe selbstständig: Unity-Playground