Menu
CoddyTech

Переключение состояния

Часть раздела Создание настоящих игр путешествия по Unity на Coddy. Урок 15 из 56.

Каждое состояние игры выполняет свою работу каждый кадр. Оператор switch по полю состояния помещает эту работу в отдельный блок case для каждого состояния, и каждый кадр выполняется ровно один блок. Состояние меняется через один метод, поэтому экран всегда соответствует текущему состоянию. В этой битве с боссом есть вступление, сражение и экран победы:

public enum Phase { Intro, Fight, Won }

public class BossFight : MonoBehaviour
{
    public GameObject introPanel;
    public GameObject fightPanel;
    public GameObject winPanel;
    public int bossHp = 10;
    private Phase phase;
    private float timer = 3f;

    void Start()
    {
        Enter(Phase.Intro);
    }

    void Update()
    {
        switch (phase)
        {
            case Phase.Intro:
                timer -= Time.deltaTime;
                if (timer <= 0f) Enter(Phase.Fight);
                break;
            case Phase.Fight:
                if (bossHp <= 0) Enter(Phase.Won);
                break;
            case Phase.Won:
                break;
        }
    }

    void Enter(Phase next)
    {
        phase = next;
        introPanel.SetActive(next == Phase.Intro);
        fightPanel.SetActive(next == Phase.Fight);
        winPanel.SetActive(next == Phase.Won);
    }
}

Каждый блок case заканчивается оператором break, потому что C# не компилирует блок case, выполнение которого продолжается в следующем. Когда таймер вступления истекает, вызов Enter(Phase.Fight) меняет фазу, но блок Fight выполняется только в следующем кадре, потому что в этом кадре блок уже выбран. Если бы здесь были отдельные блоки if один за другим, за один кадр могло бы начаться сражение и выполниться код сражения.

Enter — единственное место, где меняется phase. Условие next == Phase.Fight имеет значение true только для панели сражения, поэтому один вызов показывает эту панель и скрывает две другие. Действия, которые должны выполняться при переходе в состояние, например сброс таймера, также помещаются в Enter и выполняются один раз, а не каждый кадр.

challenge icon

Задание

Легко

Гонка на нажатия: сколько раз ты сможешь нажать пробел за 5 секунд? В GameManager есть перечисление GameState (Ready, Playing, GameOver), панель для каждого состояния, а Start вызывает SetState(GameState.Ready). Напиши Update и SetState.

В Update переключайся по state:

  • Ready: нажатие пробела начинает раунд. Это нажатие не считается.
  • Playing: каждое нажатие пробела увеличивает taps на 1 и отображает значение в tapsText в виде Taps: 3. Через roundTime секунд (5) игра заканчивается.
  • GameOver: нажатие пробела возвращает в Ready.

SetState(GameState next) задаёт state и показывает только панель нового состояния. При переходе в Playing начинается раунд с 0 нажатиями, на экране отображается Taps: 0, и остаётся roundTime секунд; при переходе в GameOver результат отображается в resultText в виде Taps: 3.

Нажми Play, проведи две гонки, затем нажми Check.

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

using UnityEngine;
using TMPro;

public enum GameState { Ready, Playing, GameOver }

public class GameManager : MonoBehaviour
{
    public GameObject readyPanel;
    public GameObject playPanel;
    public GameObject gameOverPanel;
    public TMP_Text tapsText;
    public TMP_Text resultText;
    public float roundTime = 5f;
    public GameState state;
    private int taps;
    private float timeLeft;

    void Start()
    {
        SetState(GameState.Ready);
    }

    void Update()
    {
        // выполнить ветвление по state:
        // Ready: Space начинает раунд
        // Playing: Space засчитывает нажатие; когда время истекает, игра заканчивается
        // GameOver: Space возвращает в Ready
    }

    void SetState(GameState next)
    {
        state = next;
        // показывать только панель нового состояния
        // новый раунд начинается с 0 нажатий и длится roundTime секунд; в конце resultText показывает количество нажатий
    }
}
quiz iconПроверьте себя

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

Все уроки раздела Создание настоящих игр