상태 전환하기
Coddy Unity 여정의 실제 게임 만들기 섹션에 포함된 레슨. 56개 중 15번째.
게임의 각 상태는 매 프레임마다 서로 다른 작업을 수행합니다. 상태 필드에 대한 switch를 사용하면 각 상태마다 하나의 case에 해당 작업을 배치할 수 있으며, 매 프레임 정확히 하나의 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로 이어서 실행되는 case를 컴파일할 수 없기 때문입니다. 도입부의 타이머가 끝나면 Enter(Phase.Fight)가 페이즈를 변경하지만, 이 프레임에 실행할 case는 이미 선택되었으므로 Fight case는 다음 프레임에 처음 실행됩니다. if 블록을 따로 연이어 사용하면, 한 프레임에 전투를 시작하고 같은 프레임에 전투 코드를 실행할 수도 있습니다.
Enter만이 phase를 변경하는 곳입니다. next == Phase.Fight는 전투 패널에 대해서만 true이므로, 한 번 호출하면 해당 패널이 표시되고 나머지 두 패널은 숨겨집니다. 타이머 초기화처럼 상태 진입에 필요한 작업도 Enter에 넣으면 매 프레임이 아니라 한 번만 실행됩니다.
챌린지
쉬움탭 경주: 5초 동안 스페이스바를 몇 번 누를 수 있나요? GameManager에는 GameState 열거형(Ready, Playing, GameOver), 각 상태에 해당하는 패널이 있으며, Start는 SetState(GameState.Ready)를 호출합니다. Update와 SetState를 작성하세요.
Update에서 state를 기준으로 switch 문을 사용하세요.
- Ready: 스페이스바를 누르면 라운드가 시작됩니다. 이때 누른 것은 탭으로 세지 않습니다.
- Playing: 스페이스바를 누를 때마다
taps에 1을 더하고,Taps: 3처럼tapsText에 표시합니다.roundTime초(5초)가 지나면 게임이 끝납니다. - GameOver: 스페이스바를 누르면 Ready로 돌아갑니다.
SetState(GameState next)는 state를 설정하고 새 상태의 패널만 표시합니다. Playing 상태로 들어가면 탭 수를 0으로 하여 라운드를 시작하고, 화면에 Taps: 0을 표시하며 남은 시간은 roundTime초로 설정합니다. GameOver 상태로 들어가면 Taps: 3처럼 결과를 resultText에 표시합니다.
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;
// 새 state의 패널만 표시
// 새 라운드는 탭 횟수 0과 roundTime초로 시작하며, 종료 시 resultText에 탭 횟수가 표시됨
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.