[CT] 05. testest (ゲームマル2026夏コンテスト)
[ERROR-CODE-H 개발일지] 4주차 — ESC 일시정지와 마우스 반응형 Pause 화면 만들기
개발 기간: 2026.07.27 ~ 2026.08.03 담당 역할: 인터페이스 상태창 — Pause 화면, 인벤토리 및 종료 메뉴 기반 제작
3주차에는 기존 HUD를 사이버펑크 스타일로 리메이크하고, Heat 상태 효과와 Skill 아이콘, 사망 연출을 추가했다.
4주차에는 플레이 중 ESC 키를 눌렀을 때 나타나는 Pause 인터페이스를 제작하기 시작했다.
최종적으로 구상한 Pause 화면은 다음과 같은 구조였다.
- 좌측: Resume, Setting, Exit 등 상호작용 버튼
- 우측: 플레이어 상태 정보
- 우측: 현재 보유 Core 및 인벤토리
- 배경: 『ERROR-CODE-H』의 분위기에 맞는 동적 사이버펑크 효과
다만 이번 주에는 이 모든 기능을 한 번에 완성하기보다, ESC 입력을 받아 게임을 일시정지하고 Pause Panel을 표시하는 기본 구조와 동적인 배경 효과를 먼저 구현하는 데 집중했다.
상태창, 인벤토리, 설정, 종료 버튼의 실제 기능은 이후 Pause 화면 위에 추가할 수 있도록 남겨두고, 우선 일시정지 상태 자체가 안정적으로 동작하는 기반부터 만드는 것을 목표로 했다.
4주차 목표
이번 주에 계획한 작업은 다음과 같았다.
- ESC 키를 이용한 일시정지
- Pause Panel 표시
- Resume 기능을 연결할 수 있는 구조
- 마우스를 사용할 수 있도록 커서 활성화
- 게임 플레이 입력과 UI 입력 분리
- 상태창과 인벤토리를 배치할 Pause 화면 레이아웃
- UI 배경용 범용 셰이더 제작
- Pause 중에도 움직이는 동적 배경
- 마우스 위치에 반응하는 배경 변화
- Core 1 인터페이스 디자인 개선
- 이후 Core 2·3에 적용할 디자인 기준 마련
이번 주 역시 계획한 모든 항목을 억지로 한 번에 끝내기보다는, 완료한 기능과 후속 작업을 구분해가며 진행했다.
ESC 입력을 Input System에 추가하기
가장 먼저 Unity Input System의 InputSystem_Actions에 Pause 입력을 추가했다.
게임 플레이 중 ESC 키를 눌렀을 때 사용할 Pause Action을 Player Action Map에 추가하고, Pause 화면으로 진입한 이후에도 같은 ESC 키로 게임을 재개할 수 있도록 UI Action Map의 Cancel에도 ESC를 연결했다.
입력 구조는 다음과 같이 구성했다.
PlayerAction Map의Pause→ ESCUIAction Map의Cancel→ ESC- 두 입력 모두
PauseManager.OnPause()호출 - Pause 진입 시 Action Map을
Player에서UI로 변경 - Resume 시 다시
UI에서Player로 복귀
Pause 입력을 받는 메서드에서는 입력이 실제 수행된 시점인지 먼저 확인했다.
1
2
3
4
5
6
7
8
9
public void OnPause(
InputAction.CallbackContext context
)
{
if (!context.performed)
return;
TogglePause();
}
InputAction.CallbackContext는 Action의 시작, 수행, 취소 등 여러 단계에서 호출될 수 있기 때문에, context.performed를 확인해 ESC 입력이 실제로 처리된 순간에만 TogglePause()가 실행되도록 했다.
현재 Pause 상태에 따라 게임을 멈추거나 다시 시작한다.
1
2
3
4
5
6
7
public void TogglePause()
{
if (isPaused)
Resume();
else
Pause();
}
게임 플레이 중 ESC를 누르면 Pause 상태로 진입하고, Pause 화면에서 ESC를 다시 누르면 Resume 상태로 돌아가도록 구성했다.
[캡처 1 삽입 — Input Actions의 Pause와 UI Cancel 설정]
Player와UIAction Map 양쪽에 ESC 입력을 연결했다. Pause 진입 후 Action Map이 UI로 전환된 상태에서도 동일한 ESC 키로 게임을 재개할 수 있도록 구성했다.
게임 일시정지 처리
Pause 상태에 진입할 때에는 단순히 Pause Panel만 화면에 띄우지 않았다.
게임 시간, 플레이어 입력, 마우스 커서, Input Action Map을 함께 변경하여 플레이 상태 자체를 UI 조작 상태로 전환하도록 만들었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void Pause()
{
if (isPaused)
return;
isPaused = true;
Time.timeScale = 0f;
playerController.SetInputEnabled(false);
pausePanel.SetActive(true);
Cursor.visible = true;
playerInput.SwitchCurrentActionMap("UI");
}
Pause 상태에서는 다음과 같은 처리가 이루어진다.
- 중복 Pause 실행을 방지한다.
isPaused를true로 변경한다.Time.timeScale을0으로 설정한다.- 플레이어 조작 입력을 비활성화한다.
- Pause Panel을 활성화한다.
- 마우스 커서를 표시한다.
- Input Action Map을
Player에서UI로 전환한다.
Time.timeScale = 0으로 설정하면 시간의 영향을 받는 이동, 애니메이션, 코루틴 등이 멈춘다.
여기에 플레이어 컨트롤러의 입력까지 비활성화함으로써, Pause 상태에서 이동이나 공격이 발생하지 않도록 했다.
또한 이후 Resume, Setting, Exit와 같은 버튼을 마우스로 조작할 수 있도록 커서를 화면에 표시했다.
[캡처 2 삽입 — 일반 플레이 화면과 ESC Pause 화면 비교]
ESC 키를 누르면 게임의 시간과 플레이어 입력이 정지하고, 마우스 커서와 Pause 화면이 활성화된다.
게임 재개 처리
Resume 상태에서는 Pause 과정에서 변경했던 값들을 다시 원래 상태로 복구한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void Resume()
{
if (!isPaused)
return;
isPaused = false;
Time.timeScale = 1f;
playerController.SetInputEnabled(true);
pausePanel.SetActive(false);
Cursor.visible = false;
playerInput.SwitchCurrentActionMap("Player");
}
Resume 시에는 다음과 같은 순서로 상태를 되돌린다.
isPaused를false로 변경한다.Time.timeScale을1로 복구한다.- 플레이어 입력을 다시 활성화한다.
- Pause Panel을 숨긴다.
- 마우스 커서를 숨긴다.
- Input Action Map을
UI에서Player로 되돌린다.
Pause Panel의 Resume 버튼에서도 사용할 수 있도록 공개 메서드 역시 준비했다.
1
2
3
4
public void ResumeGame()
{
Resume();
}
다만 이번 주 커밋에는 Button_Resume 오브젝트와 ResumeGame() 메서드까지는 존재하지만, 버튼의 OnClick에 해당 메서드를 실제로 연결한 기록은 남아 있지 않았다.
따라서 이번 주에 확실하게 동작하는 재개 방식은 ESC 키를 다시 누르는 방식이고, Resume 버튼은 추후 실제 기능을 연결할 수 있도록 준비한 단계였다.
추가로 오브젝트가 제거될 때 Time.timeScale이 0으로 남는 상황을 막기 위한 방어 코드도 추가했다.
1
2
3
4
private void OnDestroy()
{
Time.timeScale = 1f;
}
씬을 종료하거나 PauseManager가 제거되는 과정에서 Time.timeScale이 0인 상태로 남으면, 다음 씬에서도 게임이 멈춘 것처럼 보일 수 있다.
이를 방지하기 위해 오브젝트가 제거될 때 기본값인 1로 복구하도록 했다.
Pause 화면 레이아웃 계획
Pause 화면은 최종적으로 좌우 영역을 나누어 사용하는 형태로 계획했다.
좌측에는 플레이어가 직접 선택할 수 있는 메뉴를 배치하고, 우측에는 게임의 상태와 인벤토리를 보여주는 구조다.
좌측 메뉴 계획
- Resume
- Setting
- Exit
- 필요에 따라 추가되는 메뉴 버튼
우측 정보 계획
- 플레이어 현재 상태
- 현재 HP와 Heat
- 장착 중인 Core
- 보유 Core 또는 아이템
- 인벤토리
- 기타 상태 정보
이번 주에는 Pause Panel과 배경, 그리고 각종 버튼을 배치할 수 있는 기본 영역부터 만들었다.
테스트 씬에는 Button_Resume과 여러 테스트용 버튼 오브젝트가 추가되었지만, 실제 Setting·Exit·Inventory 기능은 아직 연결하지 않았다.
즉, 이번 주의 결과물은 완성된 상태창이나 인벤토리가 아니라 이후 상태창과 인벤토리를 담아낼 Pause 인터페이스의 기반이었다.
[캡처 3 삽입 — Pause 화면 전체 레이아웃과 향후 영역 표시]
Pause 화면의 기본 레이아웃. 좌측에는 Resume·Setting·Exit 버튼을, 우측에는 플레이어 상태와 인벤토리를 배치하는 방향으로 계획했다.
현재 구현되지 않은 부분은 블로그 이미지에서도 “예정”, “구상 중” 등의 표기를 넣어 실제 완성된 기능과 구분하는 편이 좋을 것 같다.
Pause 중 Core 전환이 가능한 문제
Pause 상태에서는 플레이어 컨트롤러의 입력을 비활성화하고, Action Map도 UI로 전환했다.
하지만 테스트 과정에서 Pause 상태에서도 숫자 키를 이용해 Core를 전환할 수 있는 문제가 남아 있다는 것을 확인했다.
당시 작업 기록에도 다음과 같이 남겼다.
현재 Pause 상태에서도 Core 전환이 가능한 문제가 있습니다. 다만 이 부분은 제가 해결할 수 있는 부분은 아닌 듯해 일단 건드리지 않았습니다. 현재 Pause는 TimeScale을 0으로 하는 방식으로 구현해둔 상태입니다.
원인은 Core 전환 입력이 PlayerController2D나 Input System의 Action Map을 통해 처리되지 않고, CoreManager.Update()에서 기존 Input API로 직접 키 입력을 확인하고 있었기 때문이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void Update()
{
for (int i = 0; i < coreSlots.Count; i++)
{
CoreSlot slot = coreSlots[i];
if (slot == null ||
slot.SelectKey == KeyCode.None)
{
continue;
}
if (Input.GetKeyDown(slot.SelectKey))
{
SetCurrentCore(i);
}
}
}
Time.timeScale을 0으로 설정하더라도 Unity의 Update()와 키 입력 확인 자체가 완전히 중단되는 것은 아니다.
또한 CoreManager는 현재 PlayerInput의 Action Map이 Player인지 UI인지 확인하지 않고 직접 숫자 키 입력을 읽고 있었다.
따라서 PauseManager에서 다음과 같은 처리를 모두 수행하더라도 Core 전환은 별도로 차단되지 않았다.
- 플레이어 컨트롤러 입력 비활성화
PlayerAction Map에서UIAction Map으로 전환Time.timeScale = 0
이를 해결하려면 CoreManager가 Pause 상태나 공용 입력 잠금 상태를 확인하도록 만들거나, Core 전환 입력 자체를 Input System Action으로 통합할 필요가 있었다.
하지만 이는 단순한 Pause UI 수정이 아니라 Core 시스템의 입력 처리 방식까지 변경해야 하는 문제였다.
따라서 이번 주에는 다른 팀원이 담당한 Core 시스템을 임의로 변경하지 않고, 원인과 해결 방향만 확인한 상태로 남겨두었다.
단순히 “Pause에서 Core가 바뀌는 버그가 있다”로 끝나는 문제가 아니라, 서로 다른 입력 방식이 하나의 프로젝트 안에서 섞여 있을 때 Pause 같은 전역 상태 제어가 어려워질 수 있다는 점을 확인한 사례였다.
[선택 캡처 4 삽입 — Pause 중 Core가 전환되는 알려진 문제]
Pause 상태에서도
CoreManager가 숫자 키를 직접 확인하고 있어 Core 전환이 가능했다. Pause UI만으로 해결할 수 있는 문제가 아니라 Core 입력 구조와 함께 수정해야 하는 항목으로 분리했다.
UI 에셋 및 폴더 구조 정리
4주차에는 UI 관련 에셋의 위치도 정리했다.
기존에는 Assets/jhkim 아래에 UI 관련 파일들이 위치해 있었지만, 이를 Assets/WorkSpace/jhkim으로 이동하여 팀 프로젝트의 작업 폴더 구조에 맞췄다.
이동된 항목에는 다음과 같은 파일들이 포함되어 있었다.
- HUD 프리팹
- HP·Heat·Core Drawer
- Skill UI 관련 코드
- Death UI 관련 코드
- UI 테스트 씬
- 폰트
- Material 및 Shader Graph
- 임시 UI 이미지
파일을 이동할 때에는 .meta 파일 역시 함께 유지하여 Unity 에셋의 GUID 참조가 끊어지지 않도록 했다.
또한 사용하지 않게 된 임시 에셋들은 바로 삭제하지 않고 TrashCan 폴더로 옮겼다.
팀 프로젝트에서는 내가 사용하지 않는다고 생각한 에셋이 다른 씬이나 프리팹에서 참조되고 있을 가능성이 있기 때문에, 바로 제거하기보다 먼저 분리해서 보관하는 쪽을 선택했다.
Core 1 디자인 개선
Pause 화면 작업과 함께 Core 1의 UI 디자인도 일부 개선했다.
기존 Core 1 아이콘을 새로운 사이버펑크 스타일의 이미지로 교체하고, 해당 이미지를 Core_01의 ScriptableObject 데이터에 다시 연결했다.
이 변경은 코드가 아니라 Core_01.asset의 coreIcon 참조를 새로운 이미지로 변경하는 방식으로 이루어졌다.
3주차에는 Core 이름과 아이콘을 화면에 표시하는 기능을 만들었다면, 4주차에는 실제로 화면에 표시되는 Core 1 아이콘 자체의 디자인을 개선한 것이다.
이번 주에는 우선 Core 1을 먼저 수정하고, 이후 동일한 디자인 규칙을 Core 2와 Core 3에도 적용할 계획을 세웠다.
Heat 게이지 역시 추후 Core UI와 디자인적인 통일감을 가질 수 있도록 다시 조정할 예정이었다.
다만 Core 2·3의 신규 디자인과 Heat 게이지의 추가 리메이크는 이번 주의 완료 범위에는 포함하지 않았다.
[캡처 5 삽입 — Core 1 아이콘 디자인 전후 비교]
기존 Core 1 아이콘을 새로운 사이버펑크 디자인으로 교체했다. 이후 Core 2·3과 Heat 게이지에도 같은 디자인 규칙을 적용할 계획을 세웠다.
범용 UI Shader Graph 실험
Pause 화면의 배경에는 단순한 정적 이미지 대신, 『ERROR-CODE-H』의 사이버펑크 분위기에 어울리는 동적 셰이더를 적용하고자 했다.
처음에는 Pause 화면에만 사용하는 셰이더를 만드는 대신, 여러 UI에서 공통으로 재사용할 수 있는 범용 UI Shader Graph를 제작하는 방향으로 시도했다.
구성한 기능은 다음과 같다.
- Appearance
- Distortion
- Glow
- Gradient
- Mask
- Noise
- Pixelize
- Reveal
- Scan
각각의 기능은 Sub Graph로 나누고, 이를 하나의 SG_UIFramework에서 조합하는 구조를 만들었다.
목표는 Material에서 필요한 효과만 선택해 사용할 수 있도록 만드는 것이었다.
예를 들어 UI 종류에 따라 다음과 같은 방식으로 활용하는 것을 생각했다.
- Pause 배경 → Noise, Distortion, Scan
- Core 아이콘 → Glow, Reveal
- 일반 패널 → Gradient, Mask
- 강조 UI → Pixelize, Scan
다만 실제로 테스트하면서 UI Mask를 비롯한 일부 기능이 정상적으로 동작하지 않는 문제가 발생했다.
8월 2일 커밋에도 다음과 같이 기록했다.
Shader Graph 기반으로 UI 전반에 적용하기 위한 Shader를 제작했습니다. 다만 Mask를 비롯한 일부 기능이 작동하지 않는 점을 확인했습니다. 어디가 문제인지 찾기 어려워 HLSL 기반으로 다시 작성할 생각이며, 현재 버전은 임시로 올립니다.
처음 시도한 구조가 원하는 대로 동작하지 않았지만, 문제를 숨기거나 완성된 기능처럼 처리하지 않고 현재 한계와 다음 구현 방향을 그대로 기록했다.
[캡처 6 삽입 — 범용 Shader Graph 전체와 Sub Graph 구성]
Glow, Gradient, Noise, Distortion, Mask, Scan 등의 기능을 조합할 수 있는 범용 UI Shader Graph를 실험했다. UI Mask 호환 문제를 확인한 뒤 HLSL 기반 구현으로 방향을 변경했다.
Shader Graph에서 HLSL 기반 셰이더로 전환
Shader Graph 기반의 범용 셰이더에서 UI Mask 문제가 발생하자, Pause 배경용 셰이더는 HLSL 기반의 Shader_Background.shader로 다시 제작했다.
셰이더에는 다음과 같은 속성을 마련했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
_TintColor("TintColor", Color)
= (1, 1, 1, 1)
_Opacity("Opacity", Range(0, 1))
= 1
_Progress("Progress", Range(0, 1))
= 1
_PixelCount("PixelCount", Range(1, 1024))
= 128
_GlowIntensity("GlowIntensity", Range(0, 5))
= 1
_ScanSpeed("ScanSpeed", Range(-5, 5))
= 1
_NoiseStrength("NoiseStrength", Range(0, 1))
= 0.2
_DistortionStrength(
"DistortionStrength",
Range(0, 0.1)
) = 0
이러한 값을 통해 하나의 Material 안에서 다음과 같은 표현을 조정할 수 있도록 했다.
- UI 색조
- 투명도
- 좌우 진행도
- 픽셀화 정도
- Glow 강도
- Scan 속도
- Noise 강도
- Distortion 강도
Shader Graph에서 문제가 되었던 UI Mask와의 호환을 위해 Stencil 관련 속성도 직접 추가했다.
1
2
3
4
5
6
7
8
_Stencil("Stencil Ref", Float) = 0
_StencilComp("Stencil Comp", Float) = 8
_StencilOp("Stencil Op", Float) = 0
_StencilReadMask("Stencil Read Mask", Float)
= 255
_StencilWriteMask("Stencil Write Mask", Float)
= 255
_ColorMask("Color Mask", Float) = 15
처음 만든 Shader Graph 구조를 그대로 고집하기보다, 실제 UI에서 필요했던 Mask와 Stencil 처리를 직접 다룰 수 있도록 HLSL 기반으로 방향을 바꾼 것이다.
이번 작업을 통해 만들기 편한 방식과 실제 요구사항을 만족하는 방식이 항상 같지는 않다는 점을 다시 느낄 수 있었다.
Pause 중에도 셰이더가 움직이도록 만들기
Pause 상태에서는 Time.timeScale이 0이 된다.
그런데 Pause 화면의 Noise, Scan, Distortion 효과까지 함께 멈춰버리면, 화면 전체가 단순한 정지 이미지처럼 보이게 된다.
이번 Pause 화면은 게임 자체는 멈추더라도 인터페이스는 계속 살아 움직이는, 일종의 시스템 화면처럼 보이기를 원했다.
그래서 셰이더의 시간 값을 게임 시간과 분리할 필요가 있었다.
이를 위해 Time.unscaledTime을 전역 셰이더 값으로 전달하는 DontStopShader를 추가했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void UpdateTimeParams()
{
float t = Time.unscaledTime;
Shader.SetGlobalVector(
"_UnscaledTimeParams",
new Vector4(
t * xScale,
t * yScale,
t * zScale,
t * wScale
)
);
}
Time.unscaledTime은 Time.timeScale의 영향을 받지 않는다.
따라서 게임 시간이 멈춰 있어도 _UnscaledTimeParams는 계속 증가하고, Pause 배경 셰이더의 애니메이션을 유지할 수 있다.
셰이더에서는 Unity의 기본 Time Parameter 대신 전달받은 Unscaled Time을 사용하도록 했다.
1
float4 _UnscaledTimeParams;
이를 통해 게임 플레이는 완전히 정지해 있지만 Pause 화면의 Scan과 Noise는 계속 움직이는 상태를 만들 수 있었다.
[캡처 7 삽입 — Pause 중에도 움직이는 Scan 또는 Noise 효과]
Time.timeScale이0인 Pause 상태에서도 UI 셰이더가 움직이도록Time.unscaledTime을 전역 셰이더 값으로 전달했다.
이 기능은 정적인 이미지보다 2~3초 정도의 GIF나 짧은 영상으로 보여주는 편이 훨씬 잘 드러날 것 같다.
마우스 위치에 반응하는 Pause 배경
Pause 화면에서는 마우스를 움직일 때 배경 표현도 함께 변화하도록 PauseMouseController를 추가했다.
먼저 Pause Panel을 기준으로 마우스의 로컬 좌표를 계산했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RectTransformUtility
.ScreenPointToLocalPointInRectangle(
panelRect,
Input.mousePosition,
cam,
out Vector2 localPoint
);
Rect rect = panelRect.rect;
float mouseX = Mathf.InverseLerp(
rect.xMin,
rect.xMax,
localPoint.x
);
mouseX = Mathf.Clamp01(mouseX);
마우스의 X좌표를 0~1 사이의 값으로 정규화한 뒤, 이를 다시 좌우 방향을 나타내는 값으로 변환했다.
1
2
3
4
5
6
7
8
9
10
11
float signed =
(0.5f - mouseX) * 2f;
float amplified = Mathf.Clamp(
signed * amplify,
-1f,
1f
);
float target =
center + amplified * moveRange;
마우스가 화면 중앙에 있을 때는 기준값인 center를 사용하고, 좌우로 이동할수록 moveRange 범위 안에서 목표값이 달라지도록 했다.
값이 갑자기 튀지 않도록 Lerp()를 사용해 부드럽게 이동시켰다.
이 과정에서도 Pause 상태의 영향을 받지 않도록 Time.unscaledDeltaTime을 사용했다.
1
2
3
4
5
6
7
8
9
float t = Mathf.Clamp01(
lerpSpeed * Time.unscaledDeltaTime
);
progress = Mathf.Lerp(
progress,
target,
t
);
계산된 값은 Material과 전역 Shader 변수 양쪽에 전달했다.
1
2
3
4
5
6
7
8
9
materialInstance.SetFloat(
"_Progress",
progress
);
Shader.SetGlobalFloat(
"_GlobalProgress",
progress
);
전체 흐름을 정리하면 다음과 같다.
마우스 좌우 이동 → Pause Panel 기준 로컬 좌표 계산 → X좌표를 0~1로 정규화 → 목표 Progress 계산 → Unscaled Delta Time으로 부드럽게 보간 → Material의 _Progress 변경 → Pause 배경 표현 변화
이 기능을 통해 Pause 화면은 단순히 움직이는 배경에서 한 단계 더 나아가, 플레이어의 마우스 움직임에 반응하는 인터페이스가 되었다.
[캡처 8 삽입 — 마우스 좌·중앙·우 위치에 따른 Pause 배경 비교]
Pause 화면에서 마우스를 좌우로 움직이면 셰이더의
_Progress값이 달라지고, 그에 따라 배경 표현이 유동적으로 변화한다.
이 기능 역시 정적인 비교 이미지보다 GIF로 보여주는 편이 실제 느낌을 전달하기에 더 적합할 것 같다.
PlayerController2D 클래스명 오타 수정
Pause 기능을 구현하는 과정에서는 기존 플레이어 컨트롤러의 클래스명 오타도 수정했다.
변경 전:
1
2
public class PlayerCotroller2D
: MonoBehaviour
변경 후:
1
2
public class PlayerController2D
: MonoBehaviour
기존 클래스명에는 Controller의 n이 빠져 있었다.
PauseManager에서 플레이어 컨트롤러를 참조해야 하는 상황에서 잘못된 클래스명을 그대로 확장해서 사용하는 것보다, 이 시점에서 올바른 이름으로 정리하는 편이 낫다고 판단했다.
이에 맞춰 다음과 같은 참조 역시 함께 수정했다.
PlayerHealthSwordCoreSkillPlayerController2D스크립트- Player Prefab
- Player 테스트 씬
클래스명 변경은 여러 코드와 Prefab 참조에 영향을 줄 수 있는 작업이었기 때문에, 이후 팀원이 남아 있던 일부 타입 참조도 추가로 정리했다.
GitHub 작업 기록
4주차에 내가 작업한 주요 커밋은 다음과 같다.
037656f — UI 에셋 수정 및 Pause 구현을 위한 Input System 수정
작업일: 2026.07.29 오전 6시 54분
PlayerAction Map에 Pause Action 추가- ESC 키와 Pause Action 연결
UIAction Map의 Cancel에 ESC 추가PauseManager기본 구조 추가- 초기 Pause·Resume 상태 전환 구현
- UI 에셋 수정
- Core 1과 Skill 관련 신규 이미지 추가
- UI 관련 폴더를
Assets/WorkSpace/jhkim으로 이동 - HUD 프리팹 구조 수정
dd4e92d — PlayerCotroller2D 클래스명 오타 수정 및 Pause 기능 임시 구현
작업일: 2026.07.30 오전 4시 17분
PlayerCotroller2D를PlayerController2D로 수정- 관련 코드 참조 수정
- Pause 입력 Callback 추가
Time.timeScale을 이용한 일시정지- 플레이어 입력 비활성화
- Pause Panel 활성화
- 마우스 커서 표시
Player/UIAction Map 전환- Resume 처리
- Pause 테스트 씬 연결
b79f329 — Pause 기능 작업 병합
작업일: 2026.07.30 오전 4시 19분
- Pause System 작업을 메인 작업 흐름에 병합
13b346b — Shader Graph 기반 UI용 범용 Shader 제작
작업일: 2026.08.02 오전 4시 16분
- 범용 UI Shader Graph 제작
- Appearance Sub Graph
- Distortion Sub Graph
- Glow Sub Graph
- Gradient Sub Graph
- Mask Sub Graph
- Noise Sub Graph
- Pixelize Sub Graph
- Reveal Sub Graph
- Scan Sub Graph
- 테스트 Material 및 Panel 이미지 추가
- UI Mask 등 일부 기능의 문제 확인
- HLSL 전환 계획 공유
f5fb363 — Pause 화면 추가 및 Shader 개선
작업일: 2026.08.03 오전 1시 48분
- Pause 화면 추가
- Pause Panel 및 버튼 배치 기반 구성
- HLSL 기반
Shader_Background추가 - UI Stencil 및 Mask 대응 속성 추가
DontStopShader추가- Pause 상태에서도 Shader 시간 진행
PauseMouseController추가- 마우스 위치에 따른
_Progress변화 - Core 1 신규 디자인 적용
- Pause용 신규 이미지 에셋 추가
- 사용하지 않는 임시 에셋 분리
- Heat 텍스트 표시 일부 수정
ba2f675 — Pause 화면 및 Shader 작업 병합
작업일: 2026.08.03 오전 1시 49분
- Pause 화면과 Shader 개선 작업을 메인 작업 흐름에 병합
4주차 작업 흐름 정리
이번 주의 작업 흐름을 정리하면 다음과 같다.
- Pause 화면의 최종 레이아웃을 구상했다.
PlayerAction Map에 Pause 입력을 추가했다.UIAction Map에도 ESC 입력을 추가했다.- ESC 입력을
PauseManager에 연결했다. Time.timeScale을 이용한 정지 기능을 구현했다.- Pause 상태에서 플레이어 입력을 비활성화했다.
Player와UIAction Map을 전환했다.- 마우스 커서를 표시하고 Pause Panel을 활성화했다.
- Resume 처리를 위한 메서드를 준비했다.
- Pause 중 Core 전환 문제가 남아 있음을 확인했다.
- UI 에셋과 폴더 구조를 정리했다.
- Core 1의 신규 디자인을 적용했다.
- 범용 UI Shader Graph를 제작했다.
- UI Mask 등 일부 기능의 문제를 확인했다.
- Pause 배경을 HLSL 기반 Shader로 전환했다.
- Unscaled Time을 이용해 Pause 중에도 Shader가 움직이도록 했다.
- 마우스 위치에 따라 배경이 변화하도록 구현했다.
- 상태창, 인벤토리, Setting, Exit 기능은 후속 작업으로 남겼다.
이번 주의 작업은 단순한 Pause 버튼 하나를 만드는 것에서 끝나지 않았다.
입력 전환 → 게임 상태 정지 → UI 조작 환경 구성 → Pause 전용 시각 효과 → 다른 시스템과의 입력 충돌 확인까지, 하나의 Pause 화면이 실제 게임 안에서 동작하기 위해 필요한 여러 요소를 함께 다루게 되었다.
4주차 결과
이번 주에 완료한 기능은 다음과 같다.
- ESC 키 Pause 입력
- ESC 키를 이용한 Pause·Resume 상태 전환
Player/UIAction Map 전환Time.timeScale = 0을 이용한 게임 정지- 플레이어 이동·공격 입력 비활성화
- Pause Panel 활성화
- Pause 상태에서 마우스 커서 표시
- Pause 화면 레이아웃 기반
- 범용 UI Shader Graph 실험
- Shader Graph의 UI Mask 문제 확인
- HLSL 기반 Pause 배경 Shader
- Pause 상태에서도 계속 움직이는 Shader
- 마우스 위치에 반응하는 배경 효과
- Core 1 아이콘 디자인 개선
- UI 에셋과 폴더 구조 정리
- 플레이어 컨트롤러 클래스명 오타 수정
반면 다음 기능들은 후속 작업으로 남겨두었다.
- 실제 Resume 버튼 연결
- Setting 버튼 및 설정 화면
- Exit 버튼 및 종료 처리
- 플레이어 상태창
- 인벤토리 데이터 및 UI
- Pause 중 Core 전환 차단
- Core 2·3 디자인 개선
- Core 디자인에 맞춘 Heat 게이지 추가 수정
4주차를 마치며
4주차에는 상태창이나 인벤토리부터 곧바로 제작하기보다, 그 기능들을 담아낼 Pause 화면의 기반부터 만드는 것에 집중했다.
ESC 입력을 Input System에 추가하고, Pause 상태에서는 게임 시간과 플레이어 입력을 멈추도록 했다. UI를 조작할 수 있도록 마우스 커서를 표시하고, Input Action Map 역시 Player에서 UI로 전환했다.
여기까지만 보면 비교적 평범한 Pause 기능이지만, 배경은 단순한 반투명 이미지로 끝내고 싶지 않았다.
『ERROR-CODE-H』의 분위기에 맞춰 Scan, Noise, Distortion, Glow 등을 조합할 수 있는 범용 UI Shader Graph를 먼저 시도했고, UI Mask가 정상적으로 동작하지 않는 문제가 발생하자 HLSL 기반 구현으로 방향을 바꿨다.
처음 만든 방식이 실패했지만, 그대로 억지로 끌고 가기보다 문제를 기록하고 다른 구현 방식으로 전환했다.
또한 Time.timeScale이 0인 상태에서도 Pause 화면만큼은 계속 움직일 수 있도록 Unscaled Time을 사용했다.
여기에 마우스의 위치를 셰이더의 _Progress 값과 연결하면서, 단순히 움직이는 배경을 넘어 플레이어의 움직임에 반응하는 인터페이스까지 만들어 볼 수 있었다.
테스트 과정에서는 Pause 상태에서도 Core 전환이 가능하다는 문제도 발견했다.
PauseManager에서 플레이어 입력을 비활성화하고 Action Map을 UI로 바꾸더라도, CoreManager가 별도로 기존 Input API를 사용해 숫자 키를 직접 읽고 있었기 때문이다.
결국 Pause 같은 전역 상태를 제대로 제어하려면, 단순히 하나의 스크립트만 보는 것이 아니라 프로젝트 전체에서 입력이 어떤 방식으로 처리되고 있는지까지 함께 봐야 한다는 점을 알게 되었다.
이번 주에 인벤토리나 설정 화면까지 완성하지는 못했다.
대신 앞으로 해당 기능을 추가할 수 있는 Pause 화면과 입력 전환 구조, 그리고 『ERROR-CODE-H』의 분위기를 살릴 수 있는 동적 배경의 기반을 만들었다.
1~3주차가 플레이 중 항상 보이는 HUD를 만들어가는 과정이었다면, 4주차부터는 플레이어가 게임과 상호작용하는 또 다른 인터페이스의 층을 만들기 시작한 셈이다.