Menu
CoddyTech

Verbessern

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

Wenn du auf einen Turm klickst, öffnet sich ein Fenster mit seiner Stufe und einer Schaltfläche „Upgrade“. Jede Stufe erhöht den Schaden und die Reichweite des Turms, und jedes Upgrade kostet mehr als das vorherige. Die Stufen folgen einer Regel, daher enthält das Asset die Regel statt einer Zahlenliste: die Werte auf Stufe 1, was jede Stufe hinzufügt und den Preis eines Upgrades. Methoden auf dem ScriptableObject berechnen den Rest, sodass jedes Skript, das danach fragt, dieselbe Antwort erhält. Das Erntewachstum in einem Farmspiel:

public int YieldAt(int level)
{
    return baseYield + yieldPerLevel * (level - 1);
}

Der Turm speichert nur seine eigene level, und das Fenster zeigt die Werte der nächsten Stufe neben den aktuellen, sodass der Spieler sieht, wofür das Geld ausgegeben wird. Ein Klick auf einen Turm trifft eines seiner Teile, den Sockel oder den Kopf, die Kinder des Turms sind. Deshalb findet hit.collider.GetComponentInParent<Tower>() den Turm, zu dem sie gehören: Es sucht am getroffenen Objekt und dann weiter oben in dessen Elternobjekten.

Das Fenster ist eine Benutzeroberfläche über der 3D-Ansicht, und ein Klick auf die Upgrade-Schaltfläche ist auch ein Mausklick, den der BuildManager mitbekommt. Sein Strahl geht durch die Schaltfläche bis zum Boden dahinter, und der BuildManager schließt das Fenster, bevor die Schaltfläche losgelassen wird. EventSystem.current.IsPointerOverGameObject() ist wahr, während sich der Zeiger über der Benutzeroberfläche befindet. Daher kehrt der BuildManager vorzeitig zurück und überlässt diese Klicks den Schaltflächen.

challenge icon

Aufgabe

Mittel
  1. Füge in TowerData die öffentlichen int-Felder maxLevel, upgradeCost und damagePerLevel sowie das öffentliche float-Feld rangePerLevel hinzu. Füge int DamageAt(int level) und float RangeAt(int level) hinzu: Auf Level 1 gelten der eigene Schaden und die eigene Reichweite des Assets, und jedes darüberliegende Level erhöht sie um den Betrag pro Level. Füge int UpgradeCost(int level) hinzu, den Preis für den Aufstieg von diesem Level: upgradeCost multipliziert mit dem Level.
  2. Behalte in Tower ein privates int-Feld level, das bei 1 beginnt und über public int Level => level; lesbar ist. Feuere mit DamageAt(level) und ziele innerhalb von RangeAt(level). Füge public void Upgrade() hinzu, das das Level um 1 erhöht.
  3. In BuildManager wählt ein Klick auf einen Turm diesen aus, und ein Klick auf etwas anderes wählt nichts aus (ein Klick auf ein freies Feld baut weiterhin darauf). Das serialisierte towerPanel wird nur angezeigt, wenn ein Turm ausgewählt ist, mit Arrow level 1 in towerNameText, Damage 2 > 3 und Range 4.5 > 5 in zwei Zeilen in towerStatsText sowie Upgrade 40 in upgradeLabel. Bei maxLevel zeigen die Werte nur die aktuellen Werte an, die Beschriftung lautet Max level und upgradeButton ist nicht anklickbar.
  4. Schreibe public void UpgradeSelected(), das von der Upgrade-Schaltfläche aufgerufen wird: Unterhalb des höchsten Levels soll der Turm verbessert und das Panel aktualisiert werden, wenn der GameManager die Kosten für das Upgrade bezahlen kann. Ignoriere in Update Klicks auf die UI.

Drücke Play, baue einen Turm, klicke darauf und verbessere ihn, dann Check.

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

    private Tower chosen;

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

    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) && 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);
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Unity-Spiel: Tower Defense