221 lines
6.6 KiB
Markdown
221 lines
6.6 KiB
Markdown
# 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만점일 때만 뜨는지 확인
|