# VR Beat Saber 프로젝트 인수인계 ## 현재 상태 - Unity: `6000.3.12f1` - 브랜치: `master` - 원격 저장소: `origin = https://whdwo798.synology.me/whdwo798/BeatSaber.git` - 현재 주요 작업 초점: `Assets/Scenes/Game.unity` 게임 화면, HUD, 점수/랭크, 결과 화면, 노트 체감 개선 ## 협업 규칙 - 코드 변경 전 Codex와 Claude Code가 변경 방향을 서로 검토한다. - 100점 만점 기준 80점 이상이면 진행한다. - 세부 규칙은 `COLLABORATION_RULES.md`에 정리되어 있다. ## Unity / MCP 브릿지 - `Assets/Editor/UnityCodexBridgeServer.cs` - 기본 포트 충돌 시 `19744-19748` 범위에서 fallback 하도록 수정했다. - `tools/unity-mcp-server/index.mjs` - `UNITY_BRIDGE_URL`이 없으면 Unity 브릿지 포트를 자동 탐색한다. - 최근 사용 포트는 `19745`였다. - Unity 로그에는 `Cannot find parent for ...` / UIElements RenderChain 로그가 반복될 수 있는데, 현재 확인된 범위에서는 게임 코드 컴파일 오류가 아니라 에디터 UI 쪽 로그로 보인다. ## Game 씬 HUD ### ScoreCanvas 배치 `Assets/Scenes/Game.unity` - `ScoreCanvas` 위치를 플레이어 앞쪽으로 당겼다. - Z: `17.8 -> 5` - Scale: `0.005 -> 0.006` - `applyHudPlacement`: `true -> false` - HUD가 중앙에 겹치던 문제를 줄이고, 좌우로 분리되어 보이게 했다. ### ScoreManager HUD 생성/배치 `Assets/VRBeatsKit/Scripts/UI/ScoreManager.cs` - 왼쪽 HUD: - `COMBO` - score - accuracy - rank - 오른쪽 HUD: - multiplier text - multiplier ring background - song progress bar - current time / total time - 동적 생성 Text에는 `LegacyRuntime.ttf`를 lazy 로딩해서 폰트가 비어 렌더링되지 않는 문제를 막았다. - `Resources.GetBuiltinResource`는 static initializer에서 호출하지 않도록 수정했다. - 진행 바는 `Image.fillAmount` 대신 RectTransform 폭을 직접 조절해서 더 안정적으로 표시한다. ## 노래 시간 / 완료 처리 `Assets/VRBeatsKit/Scripts/Core/AudioManager.cs` - `AudioSource.time` 접근 시 Unity가 `resource that is not a clip` 경고를 내던 문제를 피하기 위해 DSP 기반 시간을 우선 사용한다. `Assets/Script/SongController.cs` - MP3 `clip.length`가 0으로 잡힐 때를 대비해 fallback duration을 계산한다. - `song.duration` - 마지막 노트 시간 + 1초 - 결과 완료 대기에는 `clip.length`가 아니라 `_clipLength`를 사용한다. - 이 수정으로 게임 도중 갑자기 결과창이 뜨는 문제를 줄였다. ## 노트 위치 체감 `Assets/Script/SongController.cs` - 낮은 큐브가 너무 바닥에 깔려 베기 어려운 문제를 줄였다. - Y 레이어 매핑 변경: ```text 이전: lineLayer 0: -0.38 lineLayer 1: 0.00 lineLayer 2: +0.38 현재: lineLayer 0: -0.12 lineLayer 1: +0.22 lineLayer 2: +0.56 ``` - 적용값: ```csharp private const float LayerSpacing = 0.34f; private const float VerticalOffset = 0.22f; ``` ## 점수 / 랭크 / 콤보 배율 `Assets/VRBeatsKit/Scripts/UI/ScoreManager.cs` ### 점수 구조 - 총점 최대: `1,000,000` - 정확도 점수: `800,000` - 콤보 보너스: `200,000` ```text CurrentScore = 800000 * accuracyRatio + 200000 * comboRatio ``` ### 판정 가중치 ```text Perfect = 1000 Great = 900 Good = 700 Miss = 0 ``` ### 판정 시간 ```text Perfect <= 0.11s Great <= 0.20s Good <= 0.32s ``` ### 콤보 배율 초보자도 빨리 보상을 느끼도록 조정했다. ```text 0~4 combo x1.0 5~14 combo x1.1 15~29 combo x1.2 30~49 combo x1.35 50+ combo x1.5 ``` Multiplier ring 진행도도 같은 구간 기준으로 맞췄다. ### 랭크 - `M`: 최종 점수 `1,000,000` 이상 - 그 외 랭크는 `AccuracyPercent` 기준 ```text S+ >= 98% S >= 95% A >= 90% B >= 80% C >= 70% D >= 60% F < 60% ``` ### 랭크 색상 ```text M #E8B7FF 보석/프리즘 느낌 S+ #41F2FF 청록 네온 S #FFD95C 골드 A #B9FF72 B #FFE06A C #FFB15C D #FF7C7C F #A9B7C0 ``` ## 결과 화면 `Assets/VRBeatsKit/Scripts/UI/FinalScoreLabel.cs` - 기존 `scoreText` 하나에 rich text로 모든 결과를 넣는 방식에서, 결과 전용 레이아웃을 런타임 생성하는 방식으로 변경했다. - `ShowScore()`에서 기존 `Title`을 숨기고, 원래 `scoreText`를 비활성화한 뒤 결과 전용 레이아웃을 보여준다. - `ResetValues()`에서 결과 레이아웃을 숨기고 `Title`과 `scoreText`를 복원한다. 동적 생성 구조: ```text ResultLayoutRoot ├── RankShadowText ├── RankDepthText ├── RankMainText ├── ResultScoreText └── ResultComboText ``` - `RankShadowText`, `RankDepthText`, `RankMainText`를 겹쳐 랭크가 더 입체적으로 보이도록 했다. - `scoreText.font`와 `scoreText.fontSharedMaterial`을 복사해서 런타임 생성 TMP가 렌더링되지 않는 문제를 방지했다. - `M`은 연보라 main + 시안 depth로 보석 느낌을 주고, `S+`는 청록, `S`는 골드 계열로 구분한다. ## 비주얼 / 세이버 / 파티클 ### 파란색 가시성 - `Assets/VRBeatsKit/Settings/Settings.asset` - `Assets/VRBeatsKit/Scripts/Core/SaberTrailEffect.cs` - `Assets/VRBeatsKit/Scripts/Core/SliceTrailEffect.cs` - `Assets/VRBeatsKit/Scripts/Other/Spark.cs` 파란색 세이버/트레일/스파크가 너무 연해서 잘 보이지 않던 문제를 줄였다. ### 결과 팝업 / 사버 표시 - 게임오버/결과 시 세이버 표시 상태를 정리해 결과 화면이 더 읽기 쉽도록 했다. ## 주의 사항 - `dotnet build`는 Unity 패키지 참조를 일반 .NET 빌드가 못 찾는 경우가 있어 신뢰도가 낮다. Unity 에디터 컴파일 로그와 Play 모드 확인을 우선한다. - `Library/ScriptAssemblies/Assembly-CSharp.dll` timestamp가 갱신되지 않으면 Unity가 아직 스크립트를 리로드하지 않은 상태일 수 있다. - 결과 화면 레이아웃은 실제 Play 화면에서 `M`, `S+`, `1,000,000`, 긴 `MAX COMBO` 케이스로 크기/위치를 확인해야 한다. - Unity Console의 UIElements RenderChain 로그는 현재 작업한 게임 코드와 직접 연관된 컴파일 오류로 보이지 않는다. ## 다음 확인 권장 1. Game 씬 Play 후 HUD 좌우 위치 확인 2. 시간바가 실제 노래 시간에 따라 차오르는지 확인 3. 노래가 중간에 조기 종료되지 않는지 확인 4. 낮은 큐브가 베기 편해졌는지 VR에서 확인 5. 결과 화면에서 `M/S+/S/F` 등급 배지의 크기, 위치, 색상 확인 6. `M` 달성 조건이 의도대로 최종 100만점일 때만 뜨는지 확인