Menu
CoddyTech

Mach es zu deinem

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

Das Spiel braucht ein Ende. Verloren ist es, wenn die Leben auf 0 sinken, und gewonnen, wenn alle Wellen gestartet wurden und kein Gegner mehr auf dem Spielfeld ist. Der Spawner weiß, wann die letzte Welle unterwegs ist, und Enemy.All weiß, wie viele Gegner noch übrig sind. Daher wartet der Spawner, bis das Spielfeld leer ist, und löst dann ein Ereignis aus, auf das der GameManager reagiert. Eine Coroutine wartet mit WaitUntil auf eine Bedingung; dabei wird ein Lambda einmal pro Frame geprüft. Ein Rätselraum, der seinen Ausgang öffnet, sobald alle Schalter eingeschaltet sind:

yield return new WaitUntil(() => switchesOn == switches.Length);
exit.SetActive(true);

Bei beiden Spielenden wird das EndPanel mit einer Nachricht angezeigt und das Spiel mit Time.timeScale = 0 angehalten. Die Anzahl der Leben sinkt nie unter 0: Ein Tank, der 2 Leben abzieht, wenn nur noch 1 übrig ist, würde eine Prüfung auf genau 0 überspringen. Deshalb sorgt Mathf.Max dafür, dass die Anzahl bei 0 oder höher bleibt.

Mit „Erneut spielen“ wird die Szene erneut geladen. Time.timeScale gehört nicht zur Szene und behält seinen Wert beim Laden bei. Ein bei 0 angehaltenes Spiel würde also wieder eingefroren starten: Setze den Wert vor dem Laden wieder auf 1.

Gestalte das Spiel anschließend nach deinen Vorstellungen. Alles, womit es ausbalanciert wird, findest du im Inspector:

  • GameManagers des Spiels: startMoney (150) und startLives (20).
  • Die waves des Spawners: acht Zeilen mit Gegnern, Anzahl und Abstand sowie timeBetweenWaves (8).
  • Die EnemyData-Assets: Geschwindigkeit, Gesundheit, Belohnung und die Anzahl der Leben, die jeder Gegnertyp abzieht. Der Boss hat 450 Gesundheit und zieht 10 Leben ab.
  • Die TowerData-Assets: Kosten, Schaden, Reichweite, Feuerrate, die Upgrade-Werte, der Flächenschaden der Kanone und die Verlangsamung durch den Frostturm.

Mit einer gemischten Verteidigung in den Kurven des Weges, die mit steigendem Geld aufgerüstet wird, lassen sich die Standardwerte bewältigen; ein paar Türme desselben Typs reichen nicht aus. Ändere jeweils einen Wert und spiele, um herauszufinden, was er bewirkt.

challenge icon

Aufgabe

Schwer
  1. Füge in WaveSpawner public event Action AllWavesCleared hinzu. Warte, nachdem die letzte Welle losgeschickt wurde, bis Enemy.All leer ist, und löse dann das Ereignis aus.
  2. Füge in GameManager die serialisierten Felder endPanel (ein GameObject) und endText (ein TMP_Text) hinzu. Die Anzahl der Leben darf niemals unter 0 sinken, und wenn sie 0 erreicht, endet das Spiel mit Game Over. Wenn alle Wellen geschafft sind und noch Leben übrig sind, endet es mit You Win!. Beim Spielende wird das Panel mit der Nachricht angezeigt und Time.timeScale auf 0 gesetzt.
  3. Schreibe public void PlayAgain(), das der Button des Panels aufruft: Die Zeit wird wieder normal eingestellt und die aktive Szene erneut geladen.

Drücke Play und verteidige die Basis in allen acht Wellen, dann Check. Passe danach das Spiel im Inspector an und spiele es auf deine Weise.

Probier es selbst

using UnityEngine;
using TMPro;

public class GameManager : MonoBehaviour
{
    [SerializeField] private int startMoney = 100;
    [SerializeField] private int startLives = 20;
    [SerializeField] private WaveSpawner spawner;
    [SerializeField] private TMP_Text moneyText;
    [SerializeField] private TMP_Text livesText;
    [SerializeField] private TMP_Text waveText;

    private int money;
    private int lives;

    void OnEnable()
    {
        Enemy.ReachedBase += OnReachedBase;
        Enemy.Killed += OnKilled;
        spawner.WaveStarted += ShowWave;
    }

    void OnDisable()
    {
        Enemy.ReachedBase -= OnReachedBase;
        Enemy.Killed -= OnKilled;
        spawner.WaveStarted -= ShowWave;
    }

    void Start()
    {
        money = startMoney;
        lives = startLives;
        ShowMoney();
        ShowLives();
    }

    public bool TrySpend(int amount)
    {
        if (amount > money)
        {
            return false;
        }

        money -= amount;
        ShowMoney();
        return true;
    }

    public void Earn(int amount)
    {
        money += amount;
        ShowMoney();
    }

    void OnKilled(Enemy enemy)
    {
        Earn(enemy.data.reward);
    }

    void OnReachedBase(Enemy enemy)
    {
        lives -= enemy.data.damage;
        ShowLives();
    }

    void ShowMoney()
    {
        moneyText.text = "Money: " + money;
    }

    void ShowLives()
    {
        livesText.text = "Lives: " + lives;
    }

    void ShowWave(int wave, int total)
    {
        waveText.text = "Wave " + wave + "/" + total;
    }
}
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