Menu
CoddyTech

Verbessern

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

Die Schaltfläche „Verbessern“ des Panels ruft UpgradeSelected auf. Sie bezahlt über das TrySpend des GameManager, sodass ein knappes Budget nichts ändert. Auf der höchsten Stufe gibt es nichts mehr zu kaufen: Die Werte zeigen nur die aktuellen Werte an, und die Schaltfläche ist nicht interaktiv.

Das Panel liegt als UI über der 3D-Ansicht, und ein Klick auf seine Schaltfläche ist auch ein Mausklick, den der BuildManager wahrnimmt. Sein Strahl geht durch die Schaltfläche hindurch auf den Boden dahinter, und der BuildManager würde das Panel schließen, bevor die Schaltfläche losgelassen wird. EventSystem.current.IsPointerOverGameObject() ist wahr, solange sich der Mauszeiger über der UI befindet. Daher kehrt der BuildManager vorzeitig zurück und überlässt diese Klicks den Schaltflächen.

challenge icon

Aufgabe

Mittel

Rüste den ausgewählten Turm über sein Bedienfeld auf.

  1. Schreibe public void UpgradeSelected(): Unterhalb von maxLevel wird der Turm aufgerüstet und das Bedienfeld aktualisiert, wenn game.TrySpend(data.UpgradeCost(level)) die Kosten bezahlt.
  2. Bei maxLevel zeigt das Bedienfeld Damage 4 und Range 5.5 in zwei Zeilen sowie Max level an, und ein serialisierter upgradeButton ist nicht interaktiv.
  3. Gib in Update zurück, wenn EventSystem.current.IsPointerOverGameObject() zutrifft.

Drücke „Spielen“, baue einen Turm, klicke darauf und rüste ihn zweimal auf: Das Bedienfeld zeigt Max level an. Drücke dann „Prüfen“.

Probier es selbst

using UnityEngine;
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 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)
        {
            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;
        towerStatsText.text = "Damage " + data.DamageAt(level) + " > " + data.DamageAt(level + 1)
            + "\nRange " + data.RangeAt(level) + " > " + data.RangeAt(level + 1);
        upgradeLabel.text = "Upgrade " + data.UpgradeCost(level);
    }
}

Alle Lektionen in Unity-Spiel: Tower Defense

Übe selbstständig: Unity-Playground