Blog に戻る
コンテスト・成果物

[CT] 06. 5週目 — Resume・音量設定と Core 2・3 UI に対応する (GAMMARU2026夏コンテスト)

개발 기간: 2026.08.04 ~ 2026.08.09
후속 통합 커밋: 2026.08.10
담당 역할: Pause 인터페이스, 볼륨 설정, Core·Skill UI 확장


4주차에는 ESC 키를 이용한 Pause 기능과 마우스 위치에 반응하는 동적 배경을 구현했다.

Pause 상태에서는 게임 시간을 멈추고 플레이어 입력을 비활성화했으며, Input Action Map을 Player에서 UI로 전환했다. 다만 당시에는 ESC 키를 다시 누르는 방식으로만 게임을 재개할 수 있었고, 화면에 배치해둔 Resume 버튼 역시 실제 기능과는 연결되지 않은 상태였다.


5주차에는 이렇게 만들어둔 Pause 화면을 실제로 조작 가능한 메뉴로 발전시키는 작업 을 진행했다.

이번 주의 주요 작업은 다음과 같았다.

  • Resume 버튼 실제 연결
  • Master·BGM·SFX 볼륨 조절 기능 추가
  • Pause 메뉴 오브젝트 구조 정리
  • 마우스 위치에 따른 메뉴 움직임 추가
  • Heat UI 위치와 형태 변경에 맞춘 Shader 수정
  • Core 2·3 신규 이미지 추가
  • Core 2·3 Skill 참조 필드 추가
  • 상태창·인벤토리 UI 후속 계획 정리
  • Pause 중 Core 전환 문제 재공유

처음에는 상태창과 인벤토리까지 함께 제작하려 했지만, 예상보다 작업량이 많았다.

따라서 이번 주에는 Pause 메뉴에서 실제로 사용할 수 있는 Resume와 볼륨 설정을 우선 구현하고, Core 2·3에도 대응할 수 있도록 UI 에셋과 참조 구조를 확장하는 데 집중했다.

Resume 버튼 실제 연결

4주차에는 Button_Resume 오브젝트와 PauseManager의 재개 로직이 각각 존재했지만, 실제 버튼의 OnClick 이벤트는 비어 있었다.

5주차에는 Resume 버튼을 PauseManager.TogglePause()에 연결했다.

public void TogglePause()
{
    if (isPaused)
        Resume();
    else
        Pause();
}

Pause 상태에서 Resume 버튼을 누르면 isPaused가 true이므로 Resume()이 호출된다.

private void Resume()
{
    if (!isPaused)
        return;

    isPaused = false;
    Time.timeScale = 1f;

    playerController.SetInputEnabled(true);
    pausePanel.SetActive(false);

    Cursor.visible = false;
    playerInput.SwitchCurrentActionMap("Player");
}

Resume 버튼을 누르면 다음 상태가 원래대로 복구된다.

  • Time.timeScale을 1로 복구
  • 플레이어 입력 활성화
  • Pause Panel 비활성화
  • 마우스 커서 숨김
  • Input Action Map을 UI에서 Player로 복귀

4주차에는 ESC를 다시 눌러야만 Pause 상태에서 빠져나올 수 있었다면, 5주차부터는 화면의 Resume 버튼을 직접 클릭해 게임으로 돌아갈 수 있게 된 것 이다.


[캡처 1 삽입 — Pause 화면의 Resume 버튼]


4주차에 배치만 해두었던 Resume 버튼을 PauseManager와 연결했다. 버튼을 누르면 게임 시간과 플레이어 입력이 복구되고 Pause 화면이 닫힌다.

UI 버튼 동작을 별도 클래스로 분리

Pause 화면의 버튼 동작을 관리하기 위한 UIButtonsActions도 추가했다.

public void ResumeGame()
{
    PauseManager.Instance?.TogglePause();
}

public void OnPause(InputAction.CallbackContext context)
{
    if (!context.performed)
        return;

    PauseManager.Instance?.TogglePause();
}

public void TogglePause()
{
    PauseManager.Instance?.TogglePause();
}

이 클래스는 Resume 버튼이나 Input Action 등 여러 UI 요소에서 PauseManager의 상태 전환을 호출할 수 있는 중간 진입점 역할을 한다.

다만 5주차 당시 테스트 씬에 저장된 Resume 버튼의 실제 OnClick 연결은 UIButtonsActions.ResumeGame()이 아니라 PauseManager.TogglePause()를 직접 호출하는 형태였다.

따라서 현 단계에서는 PauseManager가 실제 Pause 상태를 관리하고, UIButtonsActions는 이후 버튼 동작을 분리하기 위해 마련한 보조적인 UI 진입점 에 가까웠다.

Pause 메뉴 오브젝트 구조 정리

Resume 버튼을 연결하는 과정에서 Pause 관련 오브젝트 구조 역시 함께 정리했다.

Pause 화면에는 다음과 같은 오브젝트들이 존재했다.

  • Pause Manager
  • Pause Panel
  • Pause Shader
  • Pause Frame
  • Pause Menu Buttons
  • Button_Resume
  • 테스트용 버튼
  • 마우스 반응형 배경 제어 오브젝트

기존에는 버튼과 Panel, PauseManager의 참조가 다소 분산되어 있어 어떤 오브젝트가 실제 상태를 관리하는지 한눈에 파악하기 어려운 부분이 있었다.

그래서 다음과 같이 책임을 기준으로 구조를 정리했다.

  • PauseManager: 실제 Pause·Resume 상태 관리
  • Pause Panel: Pause 화면 전체 표시
  • Pause Shader: 동적 배경 표시
  • Pause Menu Buttons: Resume 및 이후 추가할 메뉴 버튼 그룹
  • PauseMouseController: 마우스 위치를 Shader 값으로 변환
  • PauseMenuMotion: 마우스 위치에 따라 메뉴 위치와 크기 변경

이 과정에서 Resume 버튼이 동작하지 않던 참조 문제 역시 함께 수정했다.

단순히 기능 하나를 추가한 것이 아니라, 앞으로 Setting이나 Exit 버튼이 추가되더라도 기존 구조 안에 자연스럽게 넣을 수 있도록 Pause UI 내부의 역할을 다시 정리한 셈 이다.

마우스 위치에 따라 Pause 메뉴 움직이기

4주차에는 마우스의 X좌표를 Pause 배경 Shader의 _Progress 값과 연결했다.

5주차에는 이 값을 배경에만 사용하는 것이 아니라, 실제 메뉴 오브젝트의 움직임에도 활용하도록 확장했다.


먼저 PauseMouseController에서 현재 값을 외부에서도 읽을 수 있도록 공개했다.

public float Progress => progress;
public float Center => center;
public float MoveRange => moveRange;

PauseMenuMotion은 이 값을 받아 메뉴의 위치와 크기를 변경한다.

float progress = controller.Progress;

float center = controller.Center;
float range = controller.MoveRange;

float t = Mathf.InverseLerp(center - range, center + range, progress);

현재 Progress가 설정된 범위 안에서 어느 정도 위치에 있는지를 0~1 사이의 값으로 변환한다.

이 값을 이용해 메뉴를 좌우 또는 대각선 방향으로 이동시켰다.

Vector2 dir = new Vector2(Mathf.Cos(moveAngle * Mathf.Deg2Rad), Mathf.Sin(moveAngle * Mathf.Deg2Rad));

float move = Mathf.Lerp(-moveDistance, moveDistance, t);

rect.anchoredPosition = defaultPos + dir * move;

마우스 위치에 따라 메뉴의 크기 역시 함께 변화하도록 했다.

float scale = Mathf.Lerp(minScale, maxScale, t);

rect.localScale = defaultScale * scale;

이제 Pause 화면에서 마우스를 좌우로 움직이면 배경 Shader만 변화하는 것이 아니라, 메뉴 오브젝트 역시 미세하게 이동하고 확대·축소된다.

4주차에는 배경만 마우스에 반응 했다면, 5주차에는 메뉴까지 같은 값을 공유하면서 화면 전체가 하나의 인터페이스처럼 움직이도록 확장한 것이다.


[캡처 2 삽입 — 마우스 좌·중앙·우 위치에 따른 Pause 메뉴 변화]


PauseMouseController의 Progress 값을 메뉴에도 공유했다. 마우스 위치에 따라 Pause 배경뿐 아니라 메뉴의 위치와 크기도 함께 변화한다.

이 기능은 정적인 이미지보다는 짧은 GIF로 보여주는 편이 실제 움직임을 전달하기에 더 적합할 것 같다.

Master·BGM·SFX 볼륨 구조

Pause 메뉴에서 실제로 사용할 수 있는 기능으로, 게임의 사운드를 조절하는 볼륨 컨트롤도 추가했다.

볼륨은 다음 세 그룹으로 구분했다.

  • Master
  • BGM
  • SFX

MainAudioMixer에서는 Master 그룹을 최상위에 두고, BGM과 SFX를 그 하위 그룹으로 구성했다.

구조는 다음과 같다.

MainAudioMixer
└─ Master
 ├─ BGM
 └─ SFX


각 그룹의 볼륨을 코드에서 변경할 수 있도록 다음 파라미터를 외부에 노출했다.

  • MasterVolume
  • BGMVolume
  • SFXVolume

이를 통해 전체 음량, 배경 음악, 효과음을 각각 독립적으로 조절할 수 있도록 했다.

또한 BGM과 SFX는 Master 아래에 있기 때문에, Master 볼륨을 조절하면 두 그룹의 전체적인 음량도 함께 영향을 받는다.


[캡처 3 삽입 — MainAudioMixer의 Master·BGM·SFX 구조]


MainAudioMixer를 Master, BGM, SFX 그룹으로 나누고 각 그룹의 Volume 파라미터를 외부에 노출했다.

세 개의 볼륨 Slider 연결

VolumeController에는 Master, BGM, SFX를 각각 조절할 세 개의 Slider를 연결했다.

[Header("Audio Mixer")]
[SerializeField] private AudioMixer audioMixer;

[Header("Volume Sliders")]
[SerializeField] private Slider masterVolumeSlider;
[SerializeField] private Slider bgmVolumeSlider;
[SerializeField] private Slider sfxVolumeSlider;

씬에는 다음 Slider를 배치했다.

  • MasterVolumeSlider
  • BGM Slider
  • SFX Slider

게임이 시작되면 각 Slider의 값 변경 이벤트에 처리 메서드를 등록했다.

private void Start()
{
    masterVolumeSlider.onValueChanged.AddListener(SetMasterVolume);
    bgmVolumeSlider.onValueChanged.AddListener(SetBGMVolume);
    sfxVolumeSlider.onValueChanged.AddListener(SetSFXVolume);
}

각 Slider는 MainAudioMixer에 노출해둔 해당 파라미터와 연결된다.

private void SetMasterVolume(float value)
{
    SetVolume("MasterVolume", value);
}

private void SetBGMVolume(float value)
{
    SetVolume("BGMVolume", value);
}

private void SetSFXVolume(float value)
{
    SetVolume("SFXVolume", value);
}

하나의 공통 볼륨 변환 함수를 사용하되, 변경할 Mixer 파라미터만 다르게 전달하는 구조로 만들었다.


[캡처 4 삽입 — Pause 화면의 Master·BGM·SFX Slider]


Pause 화면에서 전체 음량과 BGM, SFX를 각각 조절할 수 있도록 세 개의 Slider를 추가했다.

Slider 값을 데시벨로 변환하기

Unity UI Slider는 일반적으로 0~1 사이의 값을 사용하지만, AudioMixer의 Volume 파라미터는 데시벨 단위로 처리된다.

따라서 Slider 값을 그대로 AudioMixer에 전달하지 않고, 로그 함수를 이용해 데시벨로 변환했다.

private void SetVolume(string parameterName, float value)
{
    float volume = value <= 0.0001f ? -80f : Mathf.Log10(value) * 20f;

    audioMixer.SetFloat(parameterName, volume);
}

Slider 값이 0에 가까울 때에는 로그 계산을 수행하지 않고 -80dB를 전달해 사실상 음소거 상태가 되도록 했다.

그 외의 값에는 다음 변환식을 사용했다.

데시벨 = log10(Slider 값) × 20


대략적으로 다음과 같이 변환된다.

  • Slider 1.0 → 약 0dB
  • Slider 0.5 → 약 -6dB
  • Slider 0.1 → 약 -20dB
  • Slider 0 → -80dB

Slider 값을 단순히 선형적인 데시벨 값과 대응시키는 것보다, 사람이 실제로 느끼는 음량 변화에 조금 더 가까운 조절이 가능하도록 로그 변환을 사용했다.

AudioSource의 Mixer 연결 조건

볼륨 Slider가 실제 게임의 사운드에 영향을 주려면, 각 AudioSource의 Output이 MainAudioMixer 계열의 그룹에 연결되어 있어야 한다.

예를 들면 다음과 같다.

  • 배경 음악 AudioSource → BGM 그룹
  • 공격·피격·Skill 효과음 → SFX 그룹
  • 아직 세부 분류하지 않은 사운드 → Master 그룹

BGM과 SFX는 Master의 하위 그룹이므로, 각각의 그룹에 연결된 AudioSource 역시 Master Slider의 영향을 함께 받는다.

반대로 AudioSource의 Output이 None으로 남아 있다면 MainAudioMixer를 거치지 않기 때문에, Slider를 움직여도 실제 사운드에는 변화가 없다.


당시 팀에도 다음 사항을 공유했다.

현재 게임에서 재생되는 AudioSource가 MainAudioMixer의 Master로 연결되어 있어야 합니다.


다만 실제 구조에서는 모든 사운드를 Master에만 연결하기보다, 사운드의 종류에 맞게 BGM과 SFX로 구분해야 각 Slider가 의도한 대로 작동한다.


[캡처 5 삽입 — AudioSource의 Output을 BGM 또는 SFX에 연결한 Inspector]


VolumeController가 정상적으로 동작하려면 게임에서 사용하는 AudioSource의 Output을 MainAudioMixer의 BGM 또는 SFX 그룹에 연결해야 한다.

5주차를 넘어 이어진 볼륨 작업

공식적인 5주차 기간은 8월 4일부터 8월 9일까지였다.

다만 MainAudioMixer, VolumeController, 세 개의 Slider와 실제 씬 참조가 저장소에 최종적으로 통합된 커밋은 다음 날인 8월 10일 에 기록되어 있다.

따라서 이번 작업은 5주차에 시작한 Pause 메뉴 확장 작업이 하루 더 이어져, 후속 커밋에서 최종적으로 통합된 것으로 정리할 수 있다.


5주차에 시작한 Volume 및 Heat UI 작업은 다음 날인 8월 10일 커밋에서 최종적으로 통합했다.


개발일지의 기간을 억지로 커밋 기록에 맞추기보다, 실제 작업 흐름과 Git 기록을 함께 남기는 편이 더 정확하다고 생각했다.

Core 2·3 신규 이미지 추가

4주차에는 Core 1의 디자인을 먼저 개선하고, 동일한 디자인 규칙을 Core 2와 Core 3에도 적용할 계획을 세웠다.

5주차에는 이를 실제 에셋으로 확장했다.


Core 1·2·3에 사용할 신규 이미지는 다음과 같이 정리했다.

  • Core1.PNG
  • Core1_Re.PNG
  • Core2.PNG
  • Core2_Re.PNG
  • Core3.PNG
  • Core3_Re.PNG

각 Core마다 일반 상태와 별도의 변형 이미지를 함께 준비하여, 이후 선택 상태나 강조 상태 등에서 활용할 수 있도록 했다.

각 Core의 ScriptableObject 데이터 역시 새로운 이미지와 연결했다.

  • Core_01.asset
  • Core_02.asset
  • Core_03.asset

3주차까지는 Core 1을 중심으로 실제 UI를 구성했다면, 5주차부터는 세 Core가 하나의 디자인 체계 안에서 보이도록 에셋을 확장한 것 이다.


[캡처 6 삽입 — Core 1·2·3 신규 디자인 비교]


Core 1에 먼저 적용했던 디자인 방향을 Core 2와 Core 3까지 확장했다. 세 Core가 동일한 HUD 안에서 하나의 디자인 체계로 보이도록 이미지를 정리했다.

SkillRefManager에 Core 2·3 참조 추가

3주차의 SkillRefManager에는 Sword Core Skill 참조만 존재했다.

5주차에는 Chain Core와 Gun Core 역시 연결할 수 있도록 참조 필드를 추가했다.

[Header("Core 1 Skill References")]
[SerializeField] private SwordCoreSkill _swordCoreSkill;

[Header("Core 2 Skill References")]
[SerializeField] private ChainCoreSkill _chainCoreSkill;

[Header("Core 3 Skill References")]
[SerializeField] private GunCoreSkill _gunCoreSkill;

Inspector에서는 다음 세 컴포넌트를 각각 연결할 수 있게 되었다.

  • Sword Core Skill
  • Chain Core Skill
  • Gun Core Skill

다만 이 시점에는 실제 이벤트 등록이 여전히 Sword Core에만 구현되어 있었다.

private void OnEnable()
{
    if (_swordCoreSkill != null)
        _swordCoreSkill.OnSkillUsed += HandleSkillUsed;
}

private void OnDisable()
{
    if (_swordCoreSkill != null)
        _swordCoreSkill.OnSkillUsed -= HandleSkillUsed;
}

즉, Chain Core와 Gun Core를 Inspector에 연결할 수 있는 필드는 추가했지만, 두 Core의 Skill 사용 이벤트가 실제 HUD까지 정상적으로 전달되는 단계는 아니었다.


당시 작업 기록에도 다음과 같이 남겼다.

Skill Ref Manager의 Reference로 Core 2, 3을 추가할 수 있습니다. 다만 아직 테스트는 못한 상태입니다.


따라서 5주차의 결과는 “Core 2·3 Skill UI 연결 완료”가 아니라, Core 2·3을 추후 연결할 수 있도록 참조 구조를 확장한 것 으로 정리하는 것이 정확하다.


[캡처 7 삽입 — SkillRefManager Inspector의 Core 1·2·3 참조]


SkillRefManager에서 Sword, Chain, Gun Core의 Skill 컴포넌트를 각각 연결할 수 있도록 참조 필드를 확장했다. Core 2·3의 실제 동작 테스트는 후속 작업으로 남겼다.

Core 2·3 Skill UI의 후속 연동

Core 2·3 참조를 추가하면서, 각 Core의 Skill 구조가 Sword Core와 완전히 동일하지 않다는 점 역시 고려할 필요가 있었다.

Sword Core에는 OnSkillUsed 이벤트가 존재했지만, 당시 Chain Core와 Gun Core에서는 UI가 같은 방식으로 사용할 수 있는 공통 이벤트가 준비되어 있지 않았다.

따라서 단순히 참조 필드만 추가한다고 해서 Skill 아이콘 애니메이션까지 자동으로 동작하는 구조는 아니었다.


이후 실제 연동을 위해서는 다음과 같은 방향 중 하나가 필요했다.

  • Chain·Gun Core에도 공통 OnSkillUsed 이벤트 추가
  • 모든 Core에서 사용할 수 있는 공통 Skill 인터페이스 제작
  • Skill 사용 이벤트를 전달하는 별도의 중계 계층 마련
  • Core별 Skill 번호를 HUD 슬롯 번호로 변환하는 로직 추가

이번 주에는 우선 구조를 확장해두는 데 그쳤고, 테스트하지 못한 동작은 완료된 기능으로 다루지 않았다.

Heat UI 위치 변경과 Shader 수정

Pause 화면과 Core UI의 디자인이 변경되면서 Heat UI의 위치와 형태 역시 함께 조정할 필요가 있었다.

기존 Heat Shader는 이전 프레임의 Fill 방향과 형태를 기준으로 만들어져 있었다.

새로운 Heat UI에서는 디자인의 방향이 바뀌었기 때문에, 기존 Shader Graph를 HeatBarShader_Old로 따로 보관하고 새로운 HeatBarShaderGraph를 추가했다.


Heat 값의 진행 방향 역시 새로운 디자인에 맞게 반대로 계산했다.

public void SetHeat(float current, bool isHighHeat)
{
    current = Mathf.Clamp(current, 0f, 100f);
    current = 100f - current;

    if (materialInstance != null)
        materialInstance.SetFloat("_Fill", current / 100f);

    if (!isOverHeat)
        heatFill.color = isHighHeat ? warningColor : normalColor;

    if (heatText != null)
        heatText.text = $"{100f - current:0}%";
}

Shader에는 반전된 Fill 값을 전달하지만, 텍스트에는 실제 Heat 수치가 그대로 표시되도록 다시 계산했다.


예를 들어 실제 Heat가 30이라면 다음과 같이 처리된다.

  • 실제 Heat: 30
  • Shader Fill 계산용 값: 70
  • 표시 텍스트: 30%

이는 새로운 Heat 프레임의 시각적인 진행 방향에 맞추기 위한 구현이었다.

플레이어에게 전달되는 의미는 그대로 유지하면서, Shader 내부에서 사용하는 값만 디자인에 맞게 반전 한 셈이다.


[캡처 8 삽입 — Heat UI 개편 전후 비교]


Heat UI의 위치와 프레임 형태가 변경되면서 Shader Graph와 Fill 계산 방향도 함께 수정했다.

HP UI에 새 Heat Shader 구조 적용 계획

Heat UI를 새로운 형태로 수정한 뒤에는 같은 시각적 규칙을 HP UI에도 적용할 계획을 세웠다.

목표는 다음과 같았다.

  • HP와 Heat의 Fill 형태 통일
  • 프레임의 기울기와 방향 통일
  • 일반·경고 상태 표현 통일
  • HUD 전체의 Material 및 Shader 관리 방식 정리

다만 HP UI 수정까지는 5주차 안에 진행하지 못했다.

당시 기록에는 다음과 같이 남겼다.

수정된 Heat 셰이더를 이용해 HP UI 또한 수정할 예정입니다. 이 또한 수요일까지 수정을 진행하겠습니다.


따라서 이번 주에는 Heat Shader 개편까지 완료하고, HP UI의 통일은 후속 작업으로 남겼다.

상태창과 인벤토리 작업 계획

4주차부터 계획했던 Pause 화면 우측의 상태창과 인벤토리 UI는 5주차에도 계속 큰 작업량을 요구하는 항목이었다.

상태창에는 다음과 같은 정보를 표시할 계획이었다.

  • 현재 HP와 Heat
  • 현재 장착 중인 Core
  • Core별 Skill 아이콘
  • 캐릭터 상태
  • 인벤토리 또는 보유 항목

특히 현재 Skill을 표시하기 위한 신규 아이콘 에셋도 함께 제작해야 했기 때문에, 단순히 UI 레이아웃만 만드는 것으로 끝나는 작업은 아니었다.

당시에는 수요일까지 상태창과 Skill 아이콘 에셋을 추가하는 것을 목표로 했지만, 5주차 기간 안에는 실제 상태창과 인벤토리를 완성하지 못했다.

따라서 이번 글에서는 어디까지나 예정된 구조 로만 소개하고, 실제 구현 결과에는 포함하지 않는다.


[캡처 9 삽입 — Pause 화면의 상태창·인벤토리 예정 영역]


Pause 화면 우측에는 현재 Core와 Skill, 캐릭터 상태, 인벤토리를 표시할 영역을 계획했다. 5주차에는 Resume와 Volume을 먼저 구현하고 상태창은 후속 작업으로 남겼다.

Pause 중 Core 전환 문제 재확인

4주차에 발견했던 Pause 중 Core 전환 문제는 5주차에도 그대로 남아 있었다.

PauseManager에서는 외부에서 현재 Pause 상태를 확인할 수 있도록 다음 속성을 제공하고 있었다.

public bool IsPaused => isPaused;

하지만 CoreManager는 이 값을 확인하지 않고, 기존 Input API를 통해 숫자 키를 직접 처리하고 있었다.

if (Input.GetKeyDown(slot.SelectKey))
{
    SetCurrentCore(i);
}

따라서 다음과 같은 Pause 처리만으로는 Core 전환을 차단할 수 없었다.

  • Time.timeScale = 0
  • PlayerController 입력 비활성화
  • Input Action Map을 UI로 전환

당시 기록에는 다음과 같이 수정 방향을 공유했다.

여전히 Pause 상태에서 Core 전환이 가능합니다. public bool IsPaused => isPaused; 코드가 있으니, 이 부분을 이용하여 Pause일 때 Core 변경을 막는 코드를 추가해 주시면 감사하겠습니다.


이 문제는 Pause 화면 자체보다는 CoreManager의 입력 처리 방식에 가까운 문제였다.

따라서 다른 팀원이 담당한 Core 시스템을 직접 수정하는 대신, 이미 제공하고 있는 Pause 상태 값과 수정 방향을 팀에 공유하는 방식 으로 대응했다.

5주차에도 해당 문제는 해결 완료 항목으로 처리하지 않았다.

GitHub 작업 기록

5주차와 바로 다음 날 이루어진 후속 통합의 관련 커밋은 다음과 같다.

18030b6 — 코어 2, 3 대응 수정

작업일: 2026.08.06 오전 4시 59분

  • SkillRefManager에 Chain Core Skill 참조 추가
  • SkillRefManager에 Gun Core Skill 참조 추가
  • PauseMouseController의 Progress 값 외부 공개
  • PauseMenuMotion 추가
  • 마우스 위치에 따른 메뉴 이동
  • 마우스 위치에 따른 메뉴 확대·축소
  • Pause 화면 구조 및 UI 폰트 수정

172c047 — Pause 기능 관련 버그 수정

작업일: 2026.08.09 오전 10시 52분

  • Resume 버튼 미동작 문제 수정
  • Resume 버튼과 PauseManager 연결
  • Pause 메뉴 설정 수정
  • Pause 관련 오브젝트 구조 정리
  • UIButtonsActions 추가
  • Core 1·2·3 신규 이미지 추가
  • Core ScriptableObject 이미지 참조 수정
  • HUD 프리팹 및 Heat Material 일부 수정

20d729d — Volume 컨트롤, Heat UI 개편

작업일: 2026.08.10 오후 8시 26분

5주차에 시작한 작업을 이어서 최종적으로 통합한 후속 커밋이다.

  • MainAudioMixer 추가
  • Master·BGM·SFX 그룹 구성
  • MasterVolume·BGMVolume·SFXVolume 외부 노출
  • VolumeController 추가
  • Master·BGM·SFX Slider 연결
  • Slider 값을 데시벨로 변환
  • Heat UI 위치와 형태 개편
  • 신규 HeatBar Shader Graph 추가
  • 기존 Heat Shader Graph 보관
  • Heat Fill 방향 변경
  • SkillRefManager 후속 수정
  • Pause 화면 UI 리소스 추가

5주차 작업 흐름 정리

이번 주의 작업 흐름을 정리하면 다음과 같다.

  1. 4주차 Pause 화면의 버튼과 오브젝트 구조를 점검했다.
  2. Resume 버튼이 동작하지 않는 문제를 수정했다.
  3. Resume 버튼을 PauseManager의 상태 전환과 연결했다.
  4. Pause 메뉴용 버튼 그룹을 정리했다.
  5. PauseMouseController의 Progress 값을 외부에 제공했다.
  6. PauseMenuMotion을 추가했다.
  7. 마우스 위치에 따라 메뉴가 이동하고 확대되도록 했다.
  8. Core 1의 디자인 방향을 Core 2와 Core 3으로 확장했다.
  9. Core 1·2·3 ScriptableObject의 이미지 참조를 수정했다.
  10. SkillRefManager에 Chain·Gun Core 참조를 추가했다.
  11. Core 2·3 Skill UI는 테스트 전 상태로 남겼다.
  12. MainAudioMixer를 Master·BGM·SFX로 구성했다.
  13. 세 개의 볼륨 Slider와 AudioMixer 파라미터를 연결했다.
  14. Slider 값을 데시벨로 변환했다.
  15. Heat UI의 위치와 형태에 맞춰 Shader Graph를 수정했다.
  16. HP UI의 Shader 통일 작업은 후속으로 남겼다.
  17. 상태창과 인벤토리는 작업량을 고려해 후속 작업으로 남겼다.
  18. Pause 중 Core 전환 문제를 다시 팀에 공유했다.

이번 주에는 새로운 화면을 하나 더 만드는 것보다, 4주차에 만든 Pause 화면을 실제로 사용할 수 있는 메뉴로 발전시키는 과정 에 더 가까웠다.

5주차 결과

이번 주와 이어진 후속 통합에서 완료한 항목은 다음과 같다.

  • 실제로 동작하는 Resume 버튼
  • Pause 메뉴 오브젝트 구조 정리
  • 마우스 반응형 메뉴 이동
  • 마우스 반응형 메뉴 확대·축소
  • Master Volume Slider
  • BGM Volume Slider
  • SFX Volume Slider
  • MainAudioMixer의 Master·BGM·SFX 그룹
  • Slider 값의 데시벨 변환
  • Core 1·2·3 신규 이미지
  • Core 1·2·3 ScriptableObject 아이콘 연결
  • SkillRefManager의 Chain·Gun Core 참조 필드
  • Heat UI 위치와 형태 개편
  • 신규 Heat Shader Graph
  • 변경된 형태에 맞춘 Heat Fill 방향 수정

반면 다음 항목들은 부분적으로 진행되었거나 후속 작업으로 남겼다.

  • Core 2·3 Skill UI의 실제 동작 테스트
  • Core별 Skill 이벤트 구조 통일
  • Pause 화면 우측 상태창
  • 인벤토리 UI
  • 현재 Skill 아이콘 에셋
  • HP UI의 새 Shader 적용
  • Setting 화면 전체 구성
  • Exit 버튼 및 게임 종료 처리
  • Pause 중 Core 전환 차단

5주차를 마치며

5주차에는 4주차에 만든 Pause 화면을 실제로 조작할 수 있는 메뉴로 발전시키는 것 에 집중했다.

먼저 연결되어 있지 않았던 Resume 버튼을 PauseManager와 연결해, 이제는 ESC뿐 아니라 화면의 버튼을 눌러서도 게임으로 돌아갈 수 있게 했다.


마우스 반응형 연출도 조금 더 확장했다.

4주차에는 배경만 마우스에 반응했다면, 이번 주에는 같은 Progress 값을 메뉴 오브젝트와 공유하면서 메뉴의 위치와 크기까지 함께 변화하도록 만들었다.

하나의 입력 값에 여러 시각 요소가 동시에 반응하면서, Pause 화면 전체가 조금 더 하나의 인터페이스처럼 느껴지기 시작했다.


볼륨 설정에서는 Master, BGM, SFX를 각각 분리했다.

Slider의 0~1 값을 로그 함수를 이용해 데시벨로 변환하고, MainAudioMixer에 노출한 각 파라미터에 전달했다. 또한 실제 사운드가 Mixer를 거쳐야 이 설정이 적용된다는 점 역시 팀에 함께 공유했다.


Core UI는 Core 1에서 시작했던 디자인을 Core 2와 Core 3까지 확장했다.

SkillRefManager 역시 Chain·Gun Core를 참조할 수 있도록 구조를 확장했지만, 아직 실제 Skill 이벤트와의 연결은 테스트하지 못했다. 따라서 참조 구조를 확장했다는 것과 실제 기능이 동작한다는 것을 구분해 기록했다.

Heat UI 역시 새 위치와 형태에 맞춰 Shader Graph와 Fill 방향을 수정했다.

같은 구조를 HP에도 적용할 계획을 세웠지만, HP UI 통일과 상태창·인벤토리는 이후 작업으로 남겼다.


그리고 4주차에 발견한 Pause 중 Core 전환 문제도 여전히 남아 있었다.

다만 이번에는 PauseManager.IsPaused라는 명확한 상태 값을 사용할 수 있었기 때문에, Core 시스템에서 해당 값을 확인해 입력을 막는 방향을 팀에 공유했다.


이번 주에도 Pause 화면의 모든 기능을 완성한 것은 아니다.

하지만 4주차에 만든 것이 어디까지나 게임을 멈추고 화면을 띄우는 기반 이었다면, 5주차에는 Resume와 볼륨 조절처럼 플레이어가 실제로 사용할 수 있는 기능이 들어가기 시작했다.

조금씩이지만, 단순한 Pause 화면이 하나의 메뉴로 변해가고 있었다.

開発期間: 2026.08.04 ~ 2026.08.09
後続統合コミット: 2026.08.10
担当役割: Pauseインターフェース、音量設定、Core・Skill UIの拡張


4週目には、ESCキーを利用したPause機能と、マウス位置に反応する動的な背景を実装した。

Pause状態ではゲーム時間を停止し、プレイヤー入力を無効化した上で、Input Action MapをPlayerからUIへ切り替えた。ただし当時は、ESCキーを再び押す方法でしかゲームを再開できず、画面上に配置していたResumeボタンも実際の機能とはまだ接続されていなかった。


5週目には、このように作っておいたPause画面を 実際に操作できるメニューへ発展させる作業 を進めた。

今週の主な作業は以下の通りであった。

  • Resumeボタンの実際の接続
  • Master・BGM・SFXの音量調節機能を追加
  • Pauseメニューのオブジェクト構造を整理
  • マウス位置に応じたメニューの動きを追加
  • Heat UIの位置・形状変更に合わせたShaderの修正
  • Core 2・3の新規画像を追加
  • Core 2・3のSkill参照フィールドを追加
  • ステータス画面・インベントリUIの後続計画を整理
  • Pause中のCore切り替え問題を再共有

当初はステータス画面とインベントリまで同時に制作する予定であったが、想定していたより作業量が多かった。

そのため今週は、Pauseメニューで実際に使用できる Resumeと音量設定を優先して実装し、Core 2・3にも対応できるようUIアセットと参照構造を拡張することに集中した。

Resumeボタンを実際に接続する

4週目にはButton_ResumeオブジェクトとPauseManagerの再開ロジックがそれぞれ存在していたものの、実際のボタンのOnClickイベントは空の状態であった。

5週目にはResumeボタンをPauseManager.TogglePause()へ接続した。

public void TogglePause()
{
    if (isPaused)
        Resume();
    else
        Pause();
}

Pause状態でResumeボタンを押すとisPausedがtrueであるため、Resume()が呼び出される。

private void Resume()
{
    if (!isPaused)
        return;

    isPaused = false;
    Time.timeScale = 1f;

    playerController.SetInputEnabled(true);
    pausePanel.SetActive(false);

    Cursor.visible = false;
    playerInput.SwitchCurrentActionMap("Player");
}

Resumeボタンを押すと、以下の状態が元に戻る。

  • Time.timeScaleを1へ戻す
  • プレイヤー入力を有効化
  • Pause Panelを無効化
  • マウスカーソルを非表示
  • Input Action MapをUIからPlayerへ戻す

4週目まではESCを再び押さなければPause状態から抜けられなかったが、5週目からは 画面上のResumeボタンを直接クリックしてゲームへ戻れるようになった。


[キャプチャ1を挿入 — Pause画面のResumeボタン]


4週目には配置だけしていたResumeボタンをPauseManagerへ接続した。ボタンを押すとゲーム時間とプレイヤー入力が復帰し、Pause画面が閉じる。

UIボタンの動作を別クラスへ分離する

Pause画面のボタン動作を管理するためのUIButtonsActionsも追加した。

public void ResumeGame()
{
    PauseManager.Instance?.TogglePause();
}

public void OnPause(InputAction.CallbackContext context)
{
    if (!context.performed)
        return;

    PauseManager.Instance?.TogglePause();
}

public void TogglePause()
{
    PauseManager.Instance?.TogglePause();
}

このクラスは、ResumeボタンやInput Actionなど複数のUI要素からPauseManagerの状態切り替えを呼び出せる中間的な入口の役割を持つ。

ただし5週目当時、テストシーンに保存されていたResumeボタンの実際のOnClick接続はUIButtonsActions.ResumeGame()ではなく、PauseManager.TogglePause()を直接呼び出す形であった。

そのため現段階では、PauseManagerが実際のPause状態を管理し、UIButtonsActionsは今後ボタンの動作を分離するために用意した 補助的なUIの入口 に近かった。

Pauseメニューのオブジェクト構造を整理する

Resumeボタンを接続する過程で、Pause関連オブジェクトの構造も同時に整理した。

Pause画面には以下のようなオブジェクトが存在していた。

  • Pause Manager
  • Pause Panel
  • Pause Shader
  • Pause Frame
  • Pause Menu Buttons
  • Button_Resume
  • テスト用ボタン
  • マウス反応型背景の制御オブジェクト

従来はボタンやPanel、PauseManagerの参照がやや分散しており、どのオブジェクトが実際の状態を管理しているのか、一目では分かりにくい部分があった。

そこで、責任を基準として以下のように構造を整理した。

  • PauseManager: 実際のPause・Resume状態を管理
  • Pause Panel: Pause画面全体を表示
  • Pause Shader: 動的背景を表示
  • Pause Menu Buttons: Resumeおよび今後追加するメニューボタンのグループ
  • PauseMouseController: マウス位置をShader値へ変換
  • PauseMenuMotion: マウス位置に応じてメニューの位置と大きさを変更

この過程で、Resumeボタンが動作しなかった参照上の問題も同時に修正した。

単純に機能を一つ追加しただけではなく、今後SettingやExitボタンを追加した際にも既存構造の中へ自然に組み込めるよう、Pause UI内部の役割を改めて整理した形 である。

マウス位置に応じてPauseメニューを動かす

4週目には、マウスのX座標をPause背景Shaderの_Progress値へ接続した。

5週目には、この値を背景だけで使用するのではなく、実際のメニューオブジェクトの動きにも利用するよう拡張した。


まずPauseMouseControllerから現在の値を外部でも読み取れるよう公開した。

public float Progress => progress;
public float Center => center;
public float MoveRange => moveRange;

PauseMenuMotionはこの値を受け取り、メニューの位置と大きさを変更する。

float progress = controller.Progress;

float center = controller.Center;
float range = controller.MoveRange;

float t = Mathf.InverseLerp(center - range, center + range, progress);

現在のProgressが設定された範囲内のどの位置にあるのかを、0~1の値へ変換する。

この値を利用して、メニューを左右または斜め方向へ移動させた。

Vector2 dir = new Vector2(Mathf.Cos(moveAngle * Mathf.Deg2Rad), Mathf.Sin(moveAngle * Mathf.Deg2Rad));

float move = Mathf.Lerp(-moveDistance, moveDistance, t);

rect.anchoredPosition = defaultPos + dir * move;

マウス位置に応じて、メニューの大きさも同時に変化するようにした。

float scale = Mathf.Lerp(minScale, maxScale, t);

rect.localScale = defaultScale * scale;

これによってPause画面上でマウスを左右へ動かすと、背景Shaderだけでなく、メニューオブジェクトもわずかに移動しながら拡大・縮小する。

4週目には 背景だけがマウスに反応していた が、5週目ではメニューも同じ値を共有することで、画面全体が一つのインターフェースとして動くように拡張した。


[キャプチャ2を挿入 — マウスの左・中央・右位置によるPauseメニューの変化]


PauseMouseControllerのProgress値をメニュー側でも共有した。マウス位置に応じてPause背景だけでなく、メニューの位置と大きさも一緒に変化する。

この機能は、静止画像よりも短いGIFで見せる方が実際の動きを伝えるには適していると思う。

Master・BGM・SFXの音量構造

Pauseメニュー上で実際に利用できる機能として、ゲームサウンドを調節するVolume Controlも追加した。

音量は以下の三つのグループに分けた。

  • Master
  • BGM
  • SFX

MainAudioMixerではMasterグループを最上位に配置し、BGMとSFXをその子グループとして構成した。

構造は以下の通りである。

MainAudioMixer
└─ Master
 ├─ BGM
 └─ SFX


各グループの音量をコードから変更できるよう、以下のパラメータを外部へ公開した。

  • MasterVolume
  • BGMVolume
  • SFXVolume

これにより、全体音量、BGM、効果音をそれぞれ独立して調節できるようにした。

またBGMとSFXはMasterの下位グループであるため、Master Volumeを変更すると、二つのグループ全体の音量にも同時に影響する。


[キャプチャ3を挿入 — MainAudioMixerのMaster・BGM・SFX構造]


MainAudioMixerをMaster、BGM、SFXグループへ分け、それぞれのVolumeパラメータを外部へ公開した。

三つのVolume Sliderを接続する

VolumeControllerには、Master、BGM、SFXをそれぞれ調節する三つのSliderを接続した。

[Header("Audio Mixer")]
[SerializeField] private AudioMixer audioMixer;

[Header("Volume Sliders")]
[SerializeField] private Slider masterVolumeSlider;
[SerializeField] private Slider bgmVolumeSlider;
[SerializeField] private Slider sfxVolumeSlider;

シーンには以下のSliderを配置した。

  • MasterVolumeSlider
  • BGM Slider
  • SFX Slider

ゲーム開始時には、それぞれのSliderの値変更イベントへ処理メソッドを登録した。

private void Start()
{
    masterVolumeSlider.onValueChanged.AddListener(SetMasterVolume);
    bgmVolumeSlider.onValueChanged.AddListener(SetBGMVolume);
    sfxVolumeSlider.onValueChanged.AddListener(SetSFXVolume);
}

各SliderはMainAudioMixerに公開しておいた対応するパラメータへ接続される。

private void SetMasterVolume(float value)
{
    SetVolume("MasterVolume", value);
}

private void SetBGMVolume(float value)
{
    SetVolume("BGMVolume", value);
}

private void SetSFXVolume(float value)
{
    SetVolume("SFXVolume", value);
}

共通の音量変換関数を一つ使用しつつ、変更するMixerパラメータだけを変えて渡す構造とした。


[キャプチャ4を挿入 — Pause画面のMaster・BGM・SFX Slider]


Pause画面から全体音量、BGM、SFXをそれぞれ調節できるよう、三つのSliderを追加した。

Sliderの値をデシベルへ変換する

Unity UI Sliderは一般的に0~1の値を使用するが、AudioMixerのVolumeパラメータはデシベル単位で処理される。

そのためSlider値をそのままAudioMixerへ渡すのではなく、対数関数を利用してデシベルへ変換した。

private void SetVolume(string parameterName, float value)
{
    float volume = value <= 0.0001f ? -80f : Mathf.Log10(value) * 20f;

    audioMixer.SetFloat(parameterName, volume);
}

Slider値が0に近い場合は対数計算を行わず、-80dBを渡すことで、事実上のミュート状態になるようにした。

それ以外の値には、以下の変換式を使用した。

デシベル = log10(Slider値) × 20


おおよそ以下のように変換される。

  • Slider 1.0 → 約0dB
  • Slider 0.5 → 約-6dB
  • Slider 0.1 → 約-20dB
  • Slider 0 → -80dB

Slider値を単純な線形のデシベル値へ対応させるよりも、人間が実際に感じる音量変化により近い調節ができるよう、対数変換を使用した。

AudioSourceのMixer接続条件

Volume Sliderを実際のゲームサウンドへ反映するには、それぞれのAudioSourceのOutputがMainAudioMixer系のグループへ接続されている必要がある。

例えば以下のようになる。

  • BGM用AudioSource → BGMグループ
  • 攻撃・被弾・Skill効果音 → SFXグループ
  • まだ細かく分類していないサウンド → Masterグループ

BGMとSFXはMasterの下位グループであるため、それぞれのグループへ接続されたAudioSourceもMaster Sliderの影響を同時に受ける。

反対にAudioSourceのOutputがNoneのままであればMainAudioMixerを通らないため、Sliderを動かしても実際のサウンドは変化しない。


当時、チームにも以下の点を共有した。

現在ゲーム内で再生されるAudioSourceがMainAudioMixerのMasterへ接続されている必要があります。


ただし実際の構造では、すべてのサウンドをMasterだけへ接続するのではなく、サウンドの種類に応じてBGMとSFXへ分ける必要があり、それによって各Sliderが意図した通りに動作する。


[キャプチャ5を挿入 — AudioSourceのOutputをBGMまたはSFXへ接続したInspector]


VolumeControllerを正常に動作させるには、ゲームで使用するAudioSourceのOutputをMainAudioMixerのBGMまたはSFXグループへ接続する必要がある。

5週目を越えて続いたVolume作業

正式な5週目の期間は、8月4日から8月9日までであった。

ただしMainAudioMixer、VolumeController、三つのSliderと実際のシーン参照がリポジトリへ最終的に統合されたコミットは、翌日の 8月10日 に記録されている。

そのため今回の作業は、5週目に開始したPauseメニュー拡張作業が一日長く続き、後続コミットで最終的に統合されたものとして整理できる。


5週目に開始したVolumeおよびHeat UI作業は、翌日の8月10日のコミットで最終的に統合した。


開発ログ上の期間を無理にコミット記録へ合わせるよりも、実際の作業の流れとGit記録を一緒に残す方がより正確であると考えた。

Core 2・3の新規画像を追加

4週目にはCore 1のデザインを先に改善し、同じデザインルールをCore 2とCore 3にも適用する計画を立てていた。

5週目には、これを実際のアセットへ拡張した。


Core 1・2・3で使用する新規画像は、以下のように整理した。

  • Core1.PNG
  • Core1_Re.PNG
  • Core2.PNG
  • Core2_Re.PNG
  • Core3.PNG
  • Core3_Re.PNG

各Coreには通常状態と別のバリエーション画像を一緒に用意し、今後選択状態や強調状態などで利用できるようにした。

それぞれのCoreのScriptableObjectデータも、新しい画像へ接続した。

  • Core_01.asset
  • Core_02.asset
  • Core_03.asset

3週目まではCore 1を中心として実際のUIを構成していたが、5週目からは 三つのCoreが一つのデザイン体系の中で見えるようアセットを拡張した 形である。


[キャプチャ6を挿入 — Core 1・2・3の新規デザイン比較]


Core 1へ先に適用していたデザインの方向性をCore 2とCore 3まで拡張した。三つのCoreが同じHUD上で一つのデザイン体系として見えるよう、画像を整理した。

SkillRefManagerにCore 2・3の参照を追加する

3週目のSkillRefManagerにはSword Core Skillの参照だけが存在していた。

5週目には、Chain CoreとGun Coreも接続できるよう参照フィールドを追加した。

[Header("Core 1 Skill References")]
[SerializeField] private SwordCoreSkill _swordCoreSkill;

[Header("Core 2 Skill References")]
[SerializeField] private ChainCoreSkill _chainCoreSkill;

[Header("Core 3 Skill References")]
[SerializeField] private GunCoreSkill _gunCoreSkill;

Inspectorでは以下の三つのコンポーネントをそれぞれ接続できるようになった。

  • Sword Core Skill
  • Chain Core Skill
  • Gun Core Skill

ただしこの時点では、実際のイベント登録は依然としてSword Coreだけに実装されていた。

private void OnEnable()
{
    if (_swordCoreSkill != null)
        _swordCoreSkill.OnSkillUsed += HandleSkillUsed;
}

private void OnDisable()
{
    if (_swordCoreSkill != null)
        _swordCoreSkill.OnSkillUsed -= HandleSkillUsed;
}

つまり、Chain CoreとGun CoreをInspector上で接続できるフィールドは追加したものの、二つのCoreのSkill使用イベントが実際のHUDまで正常に届く段階にはまだ至っていなかった。


当時の作業記録にも以下のように残している。

Skill Ref ManagerのReferenceとしてCore 2、3を追加できます。ただし、まだテストはできていない状態です。


そのため5週目の成果は「Core 2・3 Skill UIの接続完了」ではなく、今後Core 2・3を接続できるよう参照構造を拡張したもの と整理するのが正確である。


[キャプチャ7を挿入 — SkillRefManager InspectorのCore 1・2・3参照]


SkillRefManagerでSword、Chain、Gun CoreのSkillコンポーネントをそれぞれ接続できるよう参照フィールドを拡張した。Core 2・3の実際の動作テストは後続作業として残した。

Core 2・3 Skill UIの後続連携

Core 2・3の参照を追加する中で、それぞれのCoreのSkill構造がSword Coreと完全に同じではない点も考慮する必要があった。

Sword CoreにはOnSkillUsedイベントが存在していたが、当時のChain CoreとGun Coreには、UI側が同じ方式で利用できる共通イベントがまだ用意されていなかった。

そのため、単純に参照フィールドを追加するだけでSkillアイコンのアニメーションまで自動的に動作する構造ではなかった。


今後実際に連携するには、以下のような方向のいずれかが必要であった。

  • Chain・Gun Coreにも共通のOnSkillUsedイベントを追加
  • すべてのCoreで使用できる共通Skillインターフェースを制作
  • Skill使用イベントを伝達する別の中継レイヤーを用意
  • CoreごとのSkill番号をHUDスロット番号へ変換するロジックを追加

今週はまず構造を拡張するところまでにとどめ、テストできていない動作を完成済みの機能として扱わなかった。

Heat UIの位置変更とShader修正

Pause画面とCore UIのデザイン変更に伴い、Heat UIの位置と形状も一緒に調整する必要があった。

既存のHeat Shaderは、以前のフレームのFill方向と形状を基準として作られていた。

新しいHeat UIではデザインの方向が変わったため、既存Shader GraphをHeatBarShader_Oldとして別途保管し、新しいHeatBarShaderGraphを追加した。


Heat値の進行方向も、新しいデザインに合わせて逆方向に計算した。

public void SetHeat(float current, bool isHighHeat)
{
    current = Mathf.Clamp(current, 0f, 100f);
    current = 100f - current;

    if (materialInstance != null)
        materialInstance.SetFloat("_Fill", current / 100f);

    if (!isOverHeat)
        heatFill.color = isHighHeat ? warningColor : normalColor;

    if (heatText != null)
        heatText.text = $"{100f - current:0}%";
}

Shaderには反転したFill値を渡す一方、テキストには実際のHeat値がそのまま表示されるよう再計算した。


例えば実際のHeatが30であれば、以下のように処理される。

  • 実際のHeat: 30
  • Shader Fill計算用の値: 70
  • 表示テキスト: 30%

これは新しいHeatフレームの視覚的な進行方向へ合わせるための実装であった。

プレイヤーへ伝わる意味自体は変えず、Shader内部で使用する値だけをデザインに合わせて反転した 形である。


[キャプチャ8を挿入 — Heat UI改修前後の比較]


Heat UIの位置とフレーム形状が変更されたことに合わせ、Shader GraphとFillの計算方向も同時に修正した。

HP UIへ新しいHeat Shader構造を適用する計画

Heat UIを新しい形へ変更した後は、同じ視覚的なルールをHP UIにも適用する計画を立てた。

目標は以下の通りであった。

  • HPとHeatのFill形状を統一
  • フレームの傾きと方向を統一
  • 通常・警告状態の表現を統一
  • HUD全体のMaterial・Shader管理方式を整理

ただし、HP UIの修正までは5週目中に進めることができなかった。

当時の記録には以下のように残している。

修正したHeat Shaderを利用してHP UIも修正する予定です。この部分についても水曜日までに修正を進めます。


そのため今週はHeat Shaderの改修までを完了し、HP UIの統一は後続作業として残した。

ステータス画面とインベントリの作業計画

4週目から計画していたPause画面右側のステータス画面とインベントリUIは、5週目にも引き続き大きな作業量を必要とする項目であった。

ステータス画面には以下の情報を表示する予定であった。

  • 現在のHPとHeat
  • 現在装備しているCore
  • CoreごとのSkillアイコン
  • キャラクター状態
  • インベントリまたは所持項目

特に現在のSkillを表示するための新しいアイコンアセットも同時に制作する必要があったため、単純にUIレイアウトだけを作れば終わる作業ではなかった。

当時は水曜日までにステータス画面とSkillアイコンアセットを追加することを目標としていたものの、5週目の期間内には実際のステータス画面とインベントリを完成させることはできなかった。

そのため今回の記事では、あくまで 予定している構造 としてのみ紹介し、実際の実装結果には含めない。


[キャプチャ9を挿入 — Pause画面のステータス画面・インベントリ予定領域]


Pause画面右側には現在のCoreとSkill、キャラクター状態、インベントリを表示する領域を計画した。5週目ではResumeとVolumeを先に実装し、ステータス画面は後続作業として残した。

Pause中のCore切り替え問題を再確認する

4週目に発見したPause中のCore切り替え問題は、5週目にもそのまま残っていた。

PauseManagerでは外部から現在のPause状態を確認できるよう、以下のプロパティを提供していた。

public bool IsPaused => isPaused;

しかしCoreManagerはこの値を確認せず、従来のInput APIを通して数字キーを直接処理していた。

if (Input.GetKeyDown(slot.SelectKey))
{
    SetCurrentCore(i);
}

そのため以下のPause処理だけでは、Core切り替えを遮断できなかった。

  • Time.timeScale = 0
  • PlayerController入力を無効化
  • Input Action MapをUIへ切り替え

当時の記録では、以下のように修正方針を共有した。

現在もPause状態でCoreの切り替えが可能です。public bool IsPaused => isPaused;というコードがあるため、この値を利用してPause中はCore変更を防ぐ処理を追加していただければと思います。


この問題はPause画面そのものよりも、CoreManagerの入力処理方式に近い問題であった。

そのため、ほかのチームメンバーが担当していたCoreシステムを直接変更する代わりに、すでに提供しているPause状態の値と修正方針をチームへ共有する形 で対応した。

5週目でも、この問題は解決済みの項目として扱わなかった。

GitHub作業記録

5週目と、その翌日に行われた後続統合に関連するコミットは以下の通りである。

18030b6 — 코어 2, 3 대응 수정

作業日: 2026.08.06 午前4時59分

  • SkillRefManagerにChain Core Skill参照を追加
  • SkillRefManagerにGun Core Skill参照を追加
  • PauseMouseControllerのProgress値を外部へ公開
  • PauseMenuMotionを追加
  • マウス位置に応じたメニュー移動
  • マウス位置に応じたメニュー拡大・縮小
  • Pause画面構造およびUIフォントを修正

172c047 — Pause 기능 관련 버그 수정

作業日: 2026.08.09 午前10時52分

  • Resumeボタンが動作しない問題を修正
  • ResumeボタンとPauseManagerを接続
  • Pauseメニュー設定を修正
  • Pause関連オブジェクト構造を整理
  • UIButtonsActionsを追加
  • Core 1・2・3の新規画像を追加
  • Core ScriptableObjectの画像参照を修正
  • HUDプレハブおよびHeat Materialを一部修正

20d729d — Volume 컨트롤, Heat UI 개편

作業日: 2026.08.10 午後8時26分

5週目に開始した作業を続け、最終的に統合した後続コミットである。

  • MainAudioMixerを追加
  • Master・BGM・SFXグループを構成
  • MasterVolume・BGMVolume・SFXVolumeを外部へ公開
  • VolumeControllerを追加
  • Master・BGM・SFX Sliderを接続
  • Slider値をデシベルへ変換
  • Heat UIの位置と形状を改修
  • 新規HeatBar Shader Graphを追加
  • 既存Heat Shader Graphを保管
  • Heat Fillの方向を変更
  • SkillRefManagerを追加修正
  • Pause画面用UIリソースを追加

5週目の作業フロー整理

今週の作業フローを整理すると、以下の通りである。

  1. 4週目に作ったPause画面のボタンとオブジェクト構造を確認した。
  2. Resumeボタンが動作しない問題を修正した。
  3. ResumeボタンをPauseManagerの状態切り替えへ接続した。
  4. Pauseメニュー用のボタングループを整理した。
  5. PauseMouseControllerのProgress値を外部へ提供した。
  6. PauseMenuMotionを追加した。
  7. マウス位置に応じてメニューが移動・拡大するようにした。
  8. Core 1のデザイン方向をCore 2とCore 3へ拡張した。
  9. Core 1・2・3 ScriptableObjectの画像参照を修正した。
  10. SkillRefManagerにChain・Gun Core参照を追加した。
  11. Core 2・3 Skill UIはテスト前の状態として残した。
  12. MainAudioMixerをMaster・BGM・SFXで構成した。
  13. 三つのVolume SliderとAudioMixerパラメータを接続した。
  14. Slider値をデシベルへ変換した。
  15. Heat UIの位置・形状に合わせてShader Graphを修正した。
  16. HP UIのShader統一作業は後続作業として残した。
  17. ステータス画面とインベントリは作業量を考慮し、後続作業として残した。
  18. Pause中のCore切り替え問題を再びチームへ共有した。

今週は新しい画面をもう一つ増やすというよりも、4週目に作ったPause画面を実際に使用できるメニューへ発展させる過程 に近かった。

5週目の結果

今週と、それに続く後続統合で完成した項目は以下の通りである。

  • 実際に動作するResumeボタン
  • Pauseメニューのオブジェクト構造を整理
  • マウス反応型のメニュー移動
  • マウス反応型のメニュー拡大・縮小
  • Master Volume Slider
  • BGM Volume Slider
  • SFX Volume Slider
  • MainAudioMixerのMaster・BGM・SFXグループ
  • Slider値のデシベル変換
  • Core 1・2・3の新規画像
  • Core 1・2・3 ScriptableObjectのアイコン接続
  • SkillRefManagerのChain・Gun Core参照フィールド
  • Heat UIの位置・形状改修
  • 新規Heat Shader Graph
  • 変更した形状に合わせたHeat Fill方向の修正

一方、以下の項目は部分的に進めた、あるいは後続作業として残した。

  • Core 2・3 Skill UIの実際の動作テスト
  • CoreごとのSkillイベント構造の統一
  • Pause画面右側のステータス画面
  • インベントリUI
  • 現在のSkillアイコンアセット
  • HP UIへの新しいShader適用
  • Setting画面全体の構成
  • Exitボタンおよびゲーム終了処理
  • Pause中のCore切り替え防止

5週目を終えて

5週目には、4週目に作ったPause画面を 実際に操作できるメニューへ発展させること に集中した。

まず、接続されていなかったResumeボタンをPauseManagerへ接続し、ESCだけでなく画面上のボタンを押してもゲームへ戻れるようにした。


マウス反応型の演出も、さらに少し拡張した。

4週目には背景だけがマウスへ反応していたが、今週は同じProgress値をメニューオブジェクトでも共有し、メニューの位置と大きさまで一緒に変化するようにした。

一つの入力値に複数の視覚要素が同時に反応することで、Pause画面全体が少しずつ一つのインターフェースとして感じられるようになってきた。


音量設定では、Master、BGM、SFXをそれぞれ分離した。

Sliderの0~1の値を対数関数を利用してデシベルへ変換し、MainAudioMixerへ公開した各パラメータへ渡した。また、実際のサウンドがMixerを経由しなければこの設定が反映されない点も、チームへ一緒に共有した。


Core UIについては、Core 1から始めたデザインをCore 2とCore 3まで拡張した。

SkillRefManagerについてもChain・Gun Coreを参照できるよう構造を拡張したものの、実際のSkillイベントとの接続はまだテストできていなかった。そのため、参照構造を拡張したことと、実際の機能が動作することを区別して記録した。

Heat UIについても、新しい位置と形状に合わせてShader GraphとFill方向を修正した。

同じ構造をHPにも適用する計画を立てたが、HP UIの統一とステータス画面・インベントリについては後続作業として残した。


そして4週目に発見したPause中のCore切り替え問題も、依然として残っていた。

ただし今回はPauseManager.IsPausedという明確な状態値を利用できるようになっていたため、Coreシステム側でこの値を確認し、入力を遮断する方向をチームへ共有した。


今週もPause画面のすべての機能を完成させたわけではない。

しかし、4週目に作ったものがあくまで ゲームを止めて画面を表示するための基盤 であったとすれば、5週目にはResumeや音量調節のように、プレイヤーが実際に利用できる機能が入り始めた。

少しずつではあるが、単純なPause画面が一つのメニューへと変わり始めていた。

RELATED RECORDS

同じプロジェクト、または近いテーマの記録です。