중간 평가를 하기 전에,
마지막으로 만들 시스템은 게임종료가 되었을 때, 다시 게임을 시작하는 기능과 UI같은 것들을 만들 것이다.
먼저 자신의 코어나 상대의 코어가 파괴되었을 때, 게임 결과창이 나오며, 점수나 지표가 나타나고 다시 게임을 시작하거나, 메인메뉴로 돌아가는 것을 생각하고 있다.
Target이 사라졌을 때 오류
먼저 한가지 버그를 수정할 것이다. CameraMovement에서 현재 카메라가 보는 target이 사라지는 경우, 오류가 나기 때문에, 수정해준다.
CameraMovement
[SerializeField] Transform target;
[SerializeField] GameObject fallbackTarget;
void Update()
{
if(GameManager.Instance.myState == GameManager.GameState.START)
{
Move();
Scroll();
ChengeTarget();
TargetCheck();
}
}
void TargetCheck()
{
if(target == null)
{
target = fallbackTarget.transform;
}
}
void ChengeTarget()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 카메라로 부터 클릭한 월드좌표까지 광선
if (Physics.Raycast(ray, out hit, Mathf.Infinity, LayerMask.GetMask("Cube"))) // 광선에 맞은 충돌체를 담는다.
{
target = hit.transform;
fallbackTarget.transform.position = target.position;
StartCoroutine(IChangeTarget());
Debug.Log("타겟 변경");
}
}
}
}
사용한 방법은 fallbackTarget이라는 게임오브젝트를 하나 만들어, target과 같은 위치에 두는 것이다.
이때 target이 사라지게 된다면 TargetCheck함수에서 target을 fallbackTarget의 정보를 가져와 채우는 방식을 사용했다.

게임 종료 시스템
GameManager
public enum GameState
{
STANDBY, // 게임 시작전 대기화면 상태
START, // 게임 시작하고 진행하는 상태
STOP, // 게임 일시정지 상태
FINISH, // 게임이 끝난 상태
}
public GameState myState { get; private set; }
public event Action gameFinish;
public enum Winner
{
NONE,PLAYER,ENEMY,
}
public Winner winner { get; private set; }
public void CoreDestroyed(Caster DestroyedCaster)
{
myState = GameState.FINISH;
if(DestroyedCaster is EnemyAI)
{
winner = Winner.PLAYER;
Debug.Log("플레이어 승리");
}
else if(DestroyedCaster is InputController)
{
winner = Winner.ENEMY;
Debug.Log("플레이어 패배");
}
gameFinish?.Invoke();
Time.timeScale = 0f;
}
전에 만들어 두었던 GameManager의 CoreDestoryed를 확장해서 사용한다.
gameFinish라는 델리게이트를 만들어 주고, Winner라는 열거형을 만들어 준다. winner는 이긴 사용자의 값을 넣는다.
플레이어의 코어나, 적의 코어가 파괴되었을 떄, CoreDestroyed에서 현재 상태를 GameState.FINISH로 바꾸어 준다.
이후 적의 코어가 파괴되었다면 winner에 플레이어를, 플레이어의 코어가 파괴되었다면 enemy를 넣는다.
마지막에 gameFinish 델리게이트를 호출시킨다.
UIManager
[SerializeField] GameObject finishPanel;
[SerializeField] GameObject playerWin_t;
[SerializeField] GameObject enemyWin_t;
[SerializeField] GameObject retryButton;
void Start()
{
GameManager.Instance.enemySelete += enemyLevel;
GameManager.Instance.gameStart += playStart;
GameManager.Instance.gameFinish += FinishUI;
}
private void OnDisable()
{
GameManager.Instance.enemySelete -= enemyLevel;
GameManager.Instance.gameStart -= playStart;
GameManager.Instance.gameFinish -= FinishUI;
}
void FinishUI()
{
finishPanel.SetActive(true);
if(GameManager.Instance.winner == GameManager.Winner.ENEMY)
{
enemyWin_t.SetActive(true);
retryButton.SetActive(true);
}
else if(GameManager.Instance.winner == GameManager.Winner.PLAYER)
{
playerWin_t.SetActive(true);
}
}
4개의 UI오브젝트를 넣을 변수를 만들어 주고 사용한다.
FinishUI를 Start와 OnDisable에서 GameManager의 gameFinish에 구독하게 한다.
FinishUI의 경우 GameManager winner를 확인해서 표시할 UI를 구분한다.
finishPanel은 전체적인 게임종료 UI창, playerWin_t와 enemyWin_t는 승리/패배의 텍스트, retryButton의 경우 플레이어가 패배했을때만 표시되도록 한다.

Main 버튼과 Retry를 빈 게임 오브젝트로 묶고, Horizontal Layout Group으로 정렬시킨다.
이렇게 하면 Retry가 비활성화일 때는 Main 버튼이 가운데에 위치하는 것을 볼 수 있다.

'GameDev > Cubidom' 카테고리의 다른 글
| Cubidom 메인화면으로 이동 (0) | 2026.03.24 |
|---|---|
| Cubidom 게임 재시작하기 (0) | 2026.03.23 |
| Cubidom 적 난이도 세팅 (0) | 2026.03.20 |
| Cubidom 적 난이도 선택 (0) | 2026.03.19 |
| Cubidom 게임 시작 시스템 (0) | 2026.03.18 |