Переключение состояния
Часть раздела Создание настоящих игр путешествия по Unity на Coddy. Урок 15 из 60.
Каждое состояние игры выполняет свою работу в каждом кадре. Конструкция 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 и запускаются один раз, а не в каждом кадре.
Задание
ЛегкоСделай гонку нажатий длительностью 5 секунд.
- В
SetStateпоказывай только панель нового состояния. При переходе в Playing устанавливайtaps = 0,timeLeft = roundTimeиTaps: 0; при переходе в GameOver показывайTaps: 3вresultText. - В
Update()используйswitch (state): клавиша Space переводит Ready в Playing, а GameOver — в Ready; в Playing каждое нажатие Space учитывается вtapsиtapsText, пока не истечёт время.
Нажми «Играть» и проведи гонку дважды. Затем нажми «Проверить».
Попробуйте сами
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 показывает количество нажатий
}
}
Все уроки раздела Создание настоящих игр
1Текст на экране
Холст и текстПокажем счётФорматирование чиселТаймер обратного отсчётаПовторение: спидометр4Сцены и уровни
Загрузить сценуПерезапустить уровеньСледующий уровеньСохранить между сценамиПовторение: выбор уровня2Кнопки и экраны
Кнопки и onClickЛямбдыСвязи в InspectorВключение и выключение панелейШкалы здоровьяПовторение: магазин улучшений5Сохранение с помощью PlayerPrefs
Сохранение числаЗагрузка со значением по умолчаниюРекордСохранение настроекПовторение: монеты в банке3Менеджер игры
Один скрипт управляет игройОдиночкаСостояния игрыПереключение состоянияПовторение: менеджер раундов6Проект: Бесконечный раннер
Три полосыПрепятствия впередиПотренируйтесь самостоятельно: Песочница Unity