Skip to main content

UI와 게임 흐름 완성하기

Views 47약 9분생성형 AI 활용

좋은 게임은 한 장면으로 기억되지 않습니다. 시작 버튼을 누르는 순간, 점수가 오르는 순간, 실패해서 멈추는 순간, 그리고 다시 한 번을 누르는 순간이 하나의 흐름으로 이어질 때 비로소 게임처럼 느껴집니다. 이번 장에서는 바로 그 흐름을 만듭니다. 화면을 예쁘게 꾸미는 것이 목적이 아니라, 플레이어가 지금 무엇을 해야 하는지 한눈에 알게 만드는 것이 목적입니다.

UI와 게임 흐름 완성하기

uGUI와 UI Toolkit, 이번 프로젝트에서는 무엇을 쓸까

Unity에는 대표적으로 두 가지 UI 방식이 있습니다. 하나는 오래도록 많은 게임에서 써 온 uGUI이고, 다른 하나는 웹 스타일에 가까운 UI Toolkit입니다. 둘 다 좋은 도구지만, 초보자가 첫 게임을 빠르게 완성하는 상황에서는 선택 기준이 분명해야 합니다.

이번 2D 입문 프로젝트에서는 uGUI를 기본으로 선택하겠습니다. 이유는 단순합니다. Canvas 아래에 Panel, Button, TextMeshPro를 올리고 바로 화면을 만들 수 있기 때문입니다. 점수 표시, 시작 화면, 게임오버 패널, 재시작 버튼처럼 게임 화면에 즉시 붙여야 하는 요소는 uGUI가 훨씬 직관적입니다. 반면 UI Toolkit은 구조와 스타일을 분리해 관리하기 좋고, 에디터 도구나 데이터 중심 UI에서 강점을 보입니다. 하지만 지금 단계에서는 배우는 양보다 만드는 속도가 더 중요합니다.1

쉽게 말하면 이렇습니다. uGUI는 지금 당장 게임 화면을 붙이는 데 강하고, UI Toolkit은 큰 프로젝트에서 체계적으로 관리하는 데 강합니다. 오늘 우리의 목표는 멋진 메뉴 프레임워크가 아니라, 플레이가 끊기지 않는 첫 게임의 흐름입니다.

HUD는 화면의 계기판이다

플레이어는 게임 속 규칙을 설명서로 배우지 않습니다. 대부분은 화면을 보며 배웁니다. 그래서 점수, 생명, 타이머 같은 HUD는 단순한 장식이 아니라 게임의 계기판입니다. 차를 운전할 때 속도계를 보듯, 플레이어는 HUD를 보고 지금 급한 것이 무엇인지 판단합니다.

여기서 초보자가 가장 많이 하는 실수는 UI가 직접 판단까지 하게 만드는 것입니다. 예를 들어 점수 텍스트 오브젝트가 점수 계산까지 하거나, 타이머 텍스트가 게임오버 여부를 스스로 판단하게 만드는 식입니다. 이렇게 만들면 처음에는 편해 보여도, 나중에 어디서 버그가 났는지 찾기 어려워집니다.

이번 책에서는 구조를 단순하게 가져가겠습니다. 게임의 판단은 GameManager가 하고, UI는 결과만 화면에 반영합니다. UI는 배우이고, GameManager는 감독입니다. 누가 점수를 더했는지, 생명이 줄었는지, 시간이 끝났는지는 GameManager가 알고, TextMeshPro는 그 결과만 보여줍니다.

HUD를 만드는 순서는 다음처럼 가면 가장 덜 헷갈립니다.

  1. Hierarchy에서 Canvas를 만들고, Canvas Scaler를 Scale With Screen Size로 바꿉니다.

  2. 기준 해상도는 모바일 세로 화면을 염두에 두고 1080 x 1920 정도로 잡습니다.

  3. Canvas 아래에 Score, Life, Timer용 TextMeshPro 오브젝트를 만듭니다.

  4. 각 텍스트는 화면 위쪽에 배치하고 Anchor를 위 기준으로 맞춥니다.

  5. 숫자가 바뀔 때마다 GameManager 또는 UI 전담 스크립트가 텍스트를 갱신하게 합니다.

  6. 처음부터 화려한 애니메이션을 넣기보다, 읽히는 크기와 위치를 먼저 맞춥니다.

특히 모바일에서는 점수보다 생명이나 남은 시간이 더 급한 정보가 되는 경우가 많습니다. 플레이어가 1초 안에 이해해야 하는 정보일수록 더 크고 더 단순해야 합니다. 작은 숫자 세 개를 예쁘게 늘어놓는 것보다, 지금 당장 실패와 연결되는 값을 확실히 보이게 하는 편이 훨씬 좋습니다.

화면은 씬보다 먼저 상태로 나눈다

초보자에게 가장 중요한 발상 전환이 여기 있습니다. 시작 화면, 플레이 중, 일시정지, 게임오버를 각각 다른 씬으로 쪼개기 전에 먼저 상태(State) 로 나누어 생각해야 합니다. 상태로 설계하면 하나의 씬 안에서도 흐름을 자연스럽게 이어 갈 수 있고, 패널 표시와 입력 차단도 한 곳에서 관리할 수 있습니다.2

이번 프로젝트에서는 네 가지 상태만 기억하면 충분합니다.

  • Start: 시작 패널이 보이고, 게임은 아직 진행되지 않는 상태

  • Playing: 플레이어가 움직이고 점수와 시간이 실제로 변하는 상태

  • Paused: 입력과 게임 진행을 잠시 멈추고, 일시정지 패널을 보여 주는 상태

  • GameOver: 더 이상 플레이가 진행되지 않고 결과 UI와 재시작 버튼을 보여 주는 상태

이렇게 나누면 머릿속이 놀라울 만큼 정리됩니다. 예를 들어 Start 상태에서는 적이 스폰되면 안 되고, Playing 상태에서만 점수가 올라가야 하며, GameOver 상태에서는 버튼만 눌려야 합니다. 즉, 상태 하나가 바뀌면 화면과 규칙이 함께 바뀌는 구조가 됩니다.

아주 작은 상태 관리 코드는 아래처럼 시작하면 됩니다.

public enum GameState { Start, Playing, Paused, GameOver }

public class GameManager : MonoBehaviour
{
    public GameState currentState;
    public GameObject startPanel;
    public GameObject pausePanel;
    public GameObject gameOverPanel;

    public void SetState(GameState state)
    {
        currentState = state;
        startPanel.SetActive(state == GameState.Start);
        pausePanel.SetActive(state == GameState.Paused);
        gameOverPanel.SetActive(state == GameState.GameOver);
    }
}

이 코드의 핵심은 어렵지 않습니다. 지금 게임이 어떤 상태인지 기록하고, 그 상태에 맞는 패널만 켜는 것입니다. 여기에 플레이어 입력 허용 여부, 적 스폰 허용 여부, 점수 증가 허용 여부를 차례로 연결하면 게임의 흐름이 하나의 중심축 아래로 모입니다.

시작 화면은 플레이어의 첫 숨이다

처음 게임을 켰는데 곧바로 캐릭터가 떨어지거나 적이 움직이기 시작하면, 플레이어는 준비되지 않은 상태에서 밀려납니다. 시작 화면은 단순한 장식이 아니라 플레이어가 첫 숨을 고르는 시간입니다.

Start Panel에는 많은 것이 필요하지 않습니다. 게임 제목, 한 줄 설명, 그리고 큰 Start 버튼이면 충분합니다. 오히려 초보자의 첫 게임은 요소가 적을수록 좋습니다. 버튼도 작고 멋있게 만드는 것보다, 한눈에 보이고 바로 누를 수 있게 만드는 편이 낫습니다.

여기서 중요한 것은 시작 버튼을 누르기 전까지 게임 로직이 사실상 멈춰 있어야 한다는 점입니다. 아직 플레이가 시작되지 않았는데 타이머가 줄거나 적이 움직이면, 시작 화면은 장식으로 전락합니다. 그래서 Start 상태에서는 스폰 코루틴도 멈추고, 플레이어 입력도 막고, 필요한 경우 Time.timeScale을 0으로 두는 방식이 간단하고 효과적입니다.5

게임오버는 한 줄 문구가 아니라 처리 묶음이다

게임오버는 텍스트 하나 띄우는 기능이 아닙니다. 플레이어가 실패했다는 사실을 게임 전체가 동시에 이해하는 순간입니다. 그래서 게임오버가 발생하면 여러 처리가 한 번에 묶여야 합니다.

  • 더 이상 적이나 아이템이 스폰되지 않아야 합니다.

  • 플레이어 조작과 점수 증가가 중단되어야 합니다.

  • 결과를 보여 주는 패널과 문구가 나타나야 합니다.

  • 필요하면 Time.timeScale을 0으로 바꿔 게임 시간을 멈춰야 합니다.35

중요한 것은 게임오버 조건이 명확해야 한다는 점입니다. 플레이어 사망만이 유일한 실패는 아닙니다. 남은 시간이 0이 되었을 때, 중요한 오브젝트가 바닥 아래로 떨어졌을 때, 목표 점수에 도달하지 못한 채 시간이 끝났을 때도 모두 게임오버가 될 수 있습니다. Unity 학습 자료에서도 떨어진 오브젝트나 충돌 같은 분명한 사건을 기준으로 GameOver를 호출하는 방식을 보여 줍니다.34

초보자에게는 기준이 선명할수록 좋습니다. 예를 들어 이번 프로젝트라면 다음 셋 중 하나로 시작하면 좋습니다.

  • 생명이 0이 되면 게임오버

  • 제한 시간이 끝나면 게임오버

  • 플레이어가 낭떠러지 아래로 떨어지면 게임오버

이 세 가지는 테스트가 쉽고, 버그가 나도 원인을 찾기 쉽습니다. 무엇보다 플레이어도 왜 졌는지 바로 이해할 수 있습니다.

게임오버 패널은 진짜로 읽혀야 한다

Game Over 문구를 넣을 때 많은 초보자가 붉은색, 그림자, 외곽선, 번쩍이는 효과를 한꺼번에 넣습니다. 그런데 실패 직후 플레이어가 가장 먼저 보고 싶은 것은 장식이 아니라 정보입니다. 졌는지, 왜 졌는지, 다음에 무엇을 누르면 되는지. 이 세 가지만 빠르게 전달하면 충분합니다.

그래서 GameOver Panel은 아래 세 요소로 구성하면 안정적입니다.

  • 어두운 반투명 배경 Panel

  • 가운데의 Game Over 또는 실패 문구

  • 아래쪽의 Restart 버튼

필요하다면 최종 점수 한 줄을 더 넣어도 좋습니다. 하지만 첫 프로젝트에서는 문구가 길어지지 않게 하세요. 실패 화면은 설명문이 아니라 방향 표지판에 가깝습니다.

패널을 만들 때는 기본적으로 비활성화해 두었다가 GameOver 상태에서만 켜면 됩니다. Unity Learn 예제도 이 흐름을 사용합니다. 처음에는 Game Over 텍스트와 Restart 버튼을 꺼 두고, 게임이 끝나는 순간 활성화하는 방식입니다.3

조금 더 부드러운 인상을 주고 싶다면 나중에 CanvasGroup이나 Animator로 페이드 인을 추가할 수 있습니다. 하지만 순서는 분명합니다. 먼저 동작, 그다음 연출입니다. 화면 전환 애니메이션은 흐름이 이미 안정된 뒤에 넣어도 늦지 않습니다.2

버튼 하나가 다시 플레이하게 만든다

게임오버 화면이 떠도 다시 시작할 수 없다면, 플레이어는 방금 완성한 흐름에서 튕겨 나갑니다. 그래서 Restart 버튼은 생각보다 훨씬 중요합니다. 작은 기능 같지만, 이 버튼이 있어야 비로소 플레이 루프가 닫힙니다.

구현 방식은 가장 단순한 쪽으로 갑니다. 현재 씬을 다시 로드하면 됩니다. 초보자에게 이 방법이 좋은 이유는 상태 초기화, 오브젝트 재배치, 타이머 리셋, 점수 초기화를 한 번에 처리하기 쉽기 때문입니다.34

코드는 짧습니다.

using UnityEngine.SceneManagement;

public void RestartGame()
{
    Time.timeScale = 1f;
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}

여기서 Time.timeScale = 1f;를 먼저 넣는 이유를 꼭 기억하세요. 게임오버 때 시간을 멈췄다면, 재시작 직전에 다시 1로 돌려놓아야 다음 플레이가 정상 속도로 시작됩니다.5

에디터에서 연결하는 순서도 어렵지 않습니다.

  1. Canvas 아래에 Restart Button을 만듭니다.

  2. 버튼의 자식 텍스트를 Restart로 바꿉니다.

  3. Hierarchy의 GameManager 오브젝트를 버튼의 On Click() 슬롯에 드래그합니다.

  4. 함수 목록에서 GameManager -> RestartGame()을 선택합니다.

  5. 플레이해서 GameOver 상태가 되었을 때 버튼이 보이고, 눌렀을 때 현재 씬이 다시 열리는지 확인합니다.3

이 순간부터 당신의 게임은 드디어 한 판으로 끝나지 않습니다. 시작하고, 실패하고, 다시 도전하는 진짜 게임의 리듬이 생깁니다.

일시정지는 선택이 아니라 친절이다

처음 만드는 게임에서는 일시정지를 빼고 싶어질 수 있습니다. 하지만 모바일에서는 전화가 오고, 알림이 뜨고, 잠깐 손을 떼야 하는 순간이 자주 생깁니다. 일시정지는 거창한 시스템이 아니라, 플레이어를 배려하는 기능입니다.

구현 원리는 GameOver와 비슷합니다. 상태를 Paused로 바꾸고, Pause Panel을 띄우고, 시간을 멈추면 됩니다. 다만 GameOver와 다른 점은 다시 Playing으로 돌아갈 수 있어야 한다는 것입니다. Resume 버튼 하나만 있어도 충분합니다.

초보자 단계에서는 먼저 Start와 GameOver를 확실히 만든 뒤, 그다음 Paused를 추가하는 순서가 좋습니다. 흐름 설계가 이미 되어 있다면 Pause는 얹기 쉽지만, 상태 개념 없이 만들었다면 Pause는 갑자기 프로젝트 전체를 꼬이게 만듭니다.

AI에게 묻자

AI는 UI를 예쁘게 대신 만들어 주는 마술사가 아닙니다. 더 나은 선택지를 빠르게 제안해 주는 조력자에 가깝습니다. 그래서 질문이 구체적일수록 결과가 좋아집니다.

프롬프트 예시

  • 초등학생도 1초 안에 이해할 수 있는 게임오버 문구 5개를 제안해줘. 2D 점프 게임이고 문장은 8글자 안팎으로 짧게.

  • 모바일 세로 화면 기준으로 Start 버튼과 Restart 버튼의 위치를 추천해줘. 엄지손가락으로 누르기 쉬운 배치를 이유와 함께 설명해줘.

  • 점수, 생명, 타이머 중 무엇을 가장 크게 보여야 하는지 게임 디자인 관점에서 우선순위를 정해줘.

  • Unity uGUI 기준으로 HUD를 깔끔하게 보이게 하는 색상 조합 3개를 추천해줘. 배경이 밝을 때와 어두울 때를 나눠서.

AI의 답을 받았다고 끝이 아닙니다. 반드시 Unity 화면에서 직접 확인해야 합니다. 글자는 정말 읽히는지, 버튼은 정말 잘 눌리는지, 게임오버 문구가 실패 원인을 잘 전달하는지 확인하세요. UI는 결국 눈과 손으로 검증하는 작업입니다.

이 장에서 배운 것

  • 첫 2D 프로젝트에서는 uGUI가 빠르고 직관적인 선택이라는 점

  • HUD는 점수, 생명, 타이머를 보여 주는 계기판이며 로직은 GameManager가 맡아야 한다는 점

  • 시작, 플레이 중, 일시정지, 게임오버를 씬보다 먼저 상태로 설계해야 한다는 점

  • 게임오버는 실패 문구만 띄우는 것이 아니라 스폰 중단, 입력 차단, 결과 표시를 함께 처리해야 한다는 점

  • Restart 버튼을 On Click()에 연결해 현재 씬을 다시 로드하면 가장 안정적으로 재시작 루프를 만들 수 있다는 점

  • AI에게는 막연하게 예쁜 UI를 부탁하기보다, 문구 길이와 화면 배치 같은 구체적인 기준을 함께 제시해야 한다는 점

다음 장에서 만들 것

이제 게임은 처음부터 끝까지 한 판이 돌아갑니다. 하지만 아직 손맛이 조금 부족합니다. 다음 장에서는 효과음과 배경음, 카메라의 작은 흔들림, 파티클 같은 폴리싱 요소를 더해 게임이 완성되어 가는 느낌을 확실히 만들겠습니다.

  • 점프와 충돌에 어울리는 효과음을 붙입니다.

  • 배경음악으로 플레이의 리듬을 만듭니다.

  • 작은 시각 효과로 조작감과 타격감을 살립니다.

참고

1Unity UI Toolkit 완벽 가이드

2Unity Manual Creating Screen Transitions

3Unity Learn Lesson 5.3 Game Over

4GameDevAcademy Unity game over tutorial

5GameManager와 타임스케일 정리

책 목록

AI와 함께 만드는 Unity 6: 코드 한 줄 모르던 사람도 30일 안에 첫 게임을 출시하는 법

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기