Menu
CoddyTech

Сделай по-своему

Урок 25 из 25 курса Игра на Unity: Tower Defense на Coddy.

В игре нужны условия завершения. Игрок проигрывает, когда количество жизней достигает 0, и побеждает, когда отправлена каждая волна и не осталось врагов. Спавнер ждёт, пока поле опустеет, с помощью WaitUntil, который проверяет лямбда-выражение каждый кадр, а затем вызывает событие:

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

При любом исходе показывается EndPanel, а игра останавливается с помощью Time.timeScale = 0. Если танк получает 2 единицы урона, когда осталась 1 жизнь, проверка на точное значение 0 не сработает, поэтому Mathf.Max не позволяет количеству жизней опуститься ниже 0. Значение Time.timeScale сохраняется при загрузке сцены, поэтому кнопка «Играть снова» сначала устанавливает его обратно на 1.

Теперь настрой игру под себя. Здесь startMoney (150), startLives (20) и timeBetweenWaves (8) принимают значения из кода, поскольку Inspector этого игрока доступен только для чтения: измени их там, где они объявлены, и нажми «Играть». Смешанная оборона на поворотах пути, которую можно улучшать по мере поступления денег, эффективнее стандартной игры.

challenge icon

Задание

Сложно

Заверши игру, а затем настрой её в своём коде.

  1. WaveSpawner: добавь public event Action AllWavesCleared;, вызываемое после последней волны, когда Enemy.All.Count == 0 (WaitUntil).
  2. GameManager: следи, чтобы количество жизней было не меньше 0. End(message) показывает сериализованные endPanel и endText и задаёт Time.timeScale = 0: Game Over при 0 жизнях, You Win!, когда все волны пройдены.
  3. public void PlayAgain(): Time.timeScale = 1, затем перезагрузи сцену.

Нажми «Играть» и защищай базу на протяжении всех восьми волн. Затем нажми «Проверить».

Попробуйте сами

using UnityEngine;
using TMPro;

public class GameManager : MonoBehaviour
{
    [SerializeField] private int startMoney = 150;
    [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 iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Игра на Unity: Tower Defense

Потренируйтесь самостоятельно: Песочница Unity