Menu
CoddyTech

Hazlo a tu manera

Lección 18 de 18 del curso Juego de Unity: defensa de torres de Coddy.

El juego necesita un final. Se pierde cuando las vidas llegan a 0 y se gana cuando se han enviado todas las oleadas y no queda ningún enemigo en el tablero. El spawner sabe cuándo ha salido la última oleada, y Enemy.All sabe cuántos enemigos quedan, así que el spawner espera a que el tablero esté vacío y después lanza un evento al que escucha GameManager. Una corrutina espera a que se cumpla una condición con WaitUntil, que comprueba una lambda una vez por fotograma. Una sala de puzles que abre su salida cuando todos los interruptores están activados:

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

Cualquiera de los dos finales muestra el EndPanel con un mensaje y detiene el juego con Time.timeScale = 0. Las vidas nunca bajan de 0: un Tank que recibe 2 de daño cuando le queda 1 se saltaría una comprobación de exactamente 0, así que Mathf.Max las mantiene en 0 o más.

Jugar de nuevo vuelve a cargar la escena. Time.timeScale no forma parte de la escena y conserva su valor al cargarla, así que un juego detenido en 0 volvería a empezar congelado: restablécelo a 1 antes de cargar.

Después, haz que el juego sea tuyo. Todo lo que permite equilibrarlo está en el Inspector:

  • GameManager del juego: startMoney (150) y startLives (20).
  • Las waves del Spawner: ocho filas de enemigos, cantidad y separación, y timeBetweenWaves (8).
  • Los recursos EnemyData: velocidad, salud, recompensa y las vidas que quita cada tipo. El Boss tiene 450 de salud y quita 10 vidas.
  • Los recursos TowerData: coste, daño, alcance, cadencia de disparo, los valores de mejora, el daño de área del Cannon y la ralentización de la torre Frost.

Los números predeterminados se pueden superar con una defensa variada en las curvas del camino, mejorada a medida que llega el dinero; unas pocas torres de un solo tipo no aguantarán. Cambia un número cada vez y juega para notar qué efecto tiene.

challenge icon

Desafío

Difícil
  1. En WaveSpawner, agrega public event Action AllWavesCleared. Después de enviar la última oleada, espera hasta que Enemy.All esté vacío y, luego, actívalo.
  2. En GameManager, agrega los campos serializados endPanel (un GameObject) y endText (un TMP_Text). Las vidas nunca bajan de 0 y, cuando llegan a 0, el juego termina con Game Over. Cuando se hayan despejado todas las oleadas y queden vidas, termina con You Win!. Al terminar, se muestra el panel con el mensaje y se establece Time.timeScale en 0.
  3. Escribe public void PlayAgain(), que se invoca al pulsar el botón del panel: el tiempo vuelve a la normalidad y se carga de nuevo la escena activa.

Pulsa Play y defiende la base durante las ocho oleadas; después, pulsa Check. Luego, ajusta el juego en el Inspector y juégalo a tu manera.

Pruébalo tú mismo

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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Juego de Unity: defensa de torres