ThreeKingdomsSlingshot/CLAUDE.md

83 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 삼국지 슬링샷 (가제) — 에이전트 작업 지침
> 너드나비스 조직 프로젝트 ⑤ (조직 레포 `.claude/skills/너드나비스-코어룰/rules/P38.md` §P38-3 ⑤). 새 세션은 조직 레포 `공유/인계서/삼국지슬링샷_인계서.md` → 이 파일 → `README.md` 순서로만 읽고 시작한다. 조직 규칙 본문 전수 읽기 금지(C10-1).
## 프로젝트 정보
- Unity **6000.3.23f1** · 2D · 빌트인 RP · 레거시 Input(`activeInputHandler: 0`) · Portrait · 패키지 = 기본 모듈 + `com.unity.ugui 2.0.0` + `com.unity.test-framework 1.6.0` + `com.unity.pipeline 0.10.0-exp.1`(2026-11-04 P38-7 적용).
- git = 이 폴더가 레포 루트 · `main` · 원격 없음(PD 지시 시 생성). 미추적 = `Library/` `Temp/` `Logs/` `UserSettings/` `obj/`(Unity 표준 `.gitignore` · Pipeline 포트 파일 `Library/Pipeline/.unity-pipeline-port` 도 그 안).
- 기록 = 조직 레포 `공유/대화로그/삼국지슬링샷/` · 인계서 `공유/인계서/삼국지슬링샷_인계서.md` · PD 지시 로그 #1077.
## 에디터 제어 = Unity 공식 CLI + `com.unity.pipeline` (P38-7)
기본 호출은 MCP 가 아니라 **셸에서 `unity …` 직접 호출**이다(Unity 공식 권장 · 토큰 적음). `unity` 명령은 PowerShell 로 호출하되, C# 코드에 큰따옴표가 들어가는 `eval` 류는 Bash 도구로(K-DEV-026). 에디터가 둘 이상 열려 있으면 `--project-path E:\Nerdnavis\ThreeKingdomsSlingshot` 또는 환경 변수 `UNITY_PROJECT_PATH` 로 대상을 지정한다(K-DEV-024).
### 에디터가 열려 있을 때 (PD 플레이 중 반복 수정)
```
unity status --project-path . # ready 확인(포트·PID)
unity recompile --project-path . # 수정 후 재컴파일 · 컴파일 오류 0 이어야 통과
unity command --project-path . # 등록된 명령 목록(콘솔 읽기 · 메뉴 실행 등)
unity command --project-path . <명령> [인자] # 명령 실행 · --result-only 로 JSON 만
unity command --project-path . test run --mode playmode --async-tests --timeout 600 --result-only # 열린 에디터 안에서 테스트 시작(비동기 필수 · Play 진입의 도메인 리로드가 동기 요청을 끊음)
unity command --project-path . test status --result-only # 끝날 때까지 10초마다 폴링 · test list / cancel 도 있음
# ※ `unity test <proj> --mode PlayMode` 는 자체 배치 인스턴스를 띄우므로 에디터가 열려 있으면 거부된다(2026-11-04 실측 「이미 열려 있습니다」)
unity close . [--force] # 에디터 종료(저장 없이 종료 · PD 가 연 에디터는 닫지 않는다)
```
- **작업 전에 `unity command --project-path . editor status --result-only` 로 `playMode` 를 본다.** PD 가 Play 중(`playing`)이면 `Assets/` 쓰기·리컴파일 금지(편집 모드 조사·패치 준비만). 수정을 **모두** 끝낸 뒤 리컴파일 1회. 열린 에디터가 있으면 배치 실행은 `Temp/UnityLockfile` 로 막히고, PD 가 연 에디터는 닫지 않는다 → 검증이 급하면 `Assets`·`Packages`·`ProjectSettings` 만 복사한 사본 폴더(예 `E:\Nerdnavis\_tks_verify`)에서 배치 실행(2026-11-04 실측 · 새 Library 임포트 포함 수 분).
- 수치 자산에 새 필드를 넣었으면(예 `art` · `archerRangeRatio`) 기존 `BalanceConfig.asset` 에는 비어 있다 → 자산이 git 에서 미수정이면 메뉴 `TKS/Reset Balance Defaults`(= `BuildFresh`)로 재시드 · PD 가 Inspector 로 손본 흔적(git diff)이 있으면 재시드 금지 · 필드만 보충.
- 판정 = 컴파일 오류 0 + 콘솔 error 0(Unity 자체 `SearchDatabase` 인덱싱 예외는 무해).
### 에디터가 닫혀 있을 때 (배치 · 재현 가능한 실측)
```
Unity.exe -batchmode -nographics -projectPath <proj> -executeMethod TKS.EditorTools.ProjectSetup.Build -quit -logFile <log> # 컴파일 + 설정 자산·씬 생성(BuildFresh = 기본값 재시드)
Unity.exe -batchmode -nographics -projectPath <proj> -runTests -testPlatform PlayMode -testResults <xml> -logFile <log> # 플레이모드 테스트(현재 17종)
Unity.exe -projectPath <proj> -executeMethod TKS.EditorTools.ProjectSetup.AutoPlayCapture -autoplayDir <dir> -autoplayTurns 3 # GUI 자동 플레이 캡처 · 스스로 종료
```
- `Unity.exe` = `C:\Program Files\Unity\Hub\Editor\6000.3.23f1\Editor\Unity.exe`. 에디터가 같은 프로젝트를 열고 있으면 배치 실행은 못 한다(`Temp/UnityLockfile`) — 먼저 `unity status` 로 확인.
- 배치 로그 판정 = `error CS` 0 · 테스트 XML `failed="0"`.
- **에디터가 열리면서 크래시하면 oCam(화면 녹화)을 의심**: `%LOCALAPPDATA%\Unity\Editor\Editor.log` 꼬리의 스택에 `HookSurfaceDLL` → `D3D12SwapChain::Present` 가 있으면 oCam 의 D3D12 훅이 원인(2026-11-04 15:04 × 2 실측). 이 프로젝트는 그래서 Windows Graphics API 를 **D3D11 우선**으로 고정했다(`ProjectSettings.asset` `m_BuildTargetGraphicsAPIs` · 에디터도 이 설정을 따름). 그래도 크래시하면 `-force-d3d11` 인수 또는 oCam 종료. 배치 `-nographics` 는 영향 없음.
## 코드 규칙
- 전투 수치 SOT = `Assets/Resources/BalanceConfig.asset`(Inspector 조정 · 최초 시드만 `Assets/Scripts/Editor/BalanceDefaults.cs`). 코드·테스트에 수치를 직접 적지 않는다(C45).
- **아웃게임 SOT = `Assets/Data/OutGame/*.csv`(12장 · 기획 `공유/기획팀_산출물/삼국지슬링샷/tables/` 사본 · utf-8-sig · 2026-11-05 #1093 A)** — 영웅·병사(`heroes.csv` · 구 `BalanceConfig.heroes[]` 대체) · 레벨·승급·진화·장비·뽑기·보상·재화·신규 유저 초기값(`economy.csv` start_*). 고친 뒤 메뉴 `TKS/Import OutGame Data (아웃게임 데이터 임포트)`(`Editor/DataImporter` · 오류 시 자산 불변) → `Resources/OutGame/` 9 자산. 표를 바꾸면 기획 `tables/` 도 같이.
- **스킬(2026-11-05 #1093 B)** — SOT = `Assets/Data/OutGame/skills.csv`(effect_key `;` 복수 · p1~p3 · lv_scale · needs_impl) + `skill_levels.csv` → 임포트 자산 `SkillInfoDb`(effect 열 포함 · 표시 + 전투 공용). 처리기 = `Runtime/Skills/`: `SkillKeys`(51종 · 레벨 계수 방식 · 팀 키 · 표에 없는 키 = 임포트 오류) · `SkillSystem`(유닛별 쿨·예약 · 즉시형 시한 효과 · 행동 훅 · 호위 피해 분담 · HUD 한 줄) · `SkillMods`(전투 코드가 수치 질의) · `SkillRules`(상한 = 등급 + ★3 · ★5 패시브 배율 = evolve.csv skill_unlock · 레벨업 · 스킬서 판매). 전투 코드에 스킬 수치를 직접 쓰지 않고 `SkillMods` 로 읽는다. 테스트 = `Tests/PlayMode/SkillTests`. 캡처 = `-executeMethod TKS.EditorTools.DataImporter.CaptureSkills -skillDir <dir>`.
- **아웃게임 2차(2026-11-05~06 #1093 C)** — 표 10장 추가(`training` · `training_ranks` · `patrol` · `dev_tree` · `treasures` · `treasure_sets` · `chests`(+ iron/buy 열) · `tower` · `dungeons`(+ reward_amount) · `arena`(+ 상점 키)) + `economy.csv` C 키 24 → 임포트 자산 18(A 9 + C 9 · `OutGameTables.C.cs` 검증). 코드 = `OutGame/Domestic/`(`TrainingRules` 훈련 · `PatrolRules` 순찰 · `DevRules` 개발 효과 키 → 적용 지점 · `DomesticScreen`) · `OutGame/Treasure/`(`TreasureRules` 보유·세트·강화·조건 카운터·상자 · `TreasureScreen`) · `OutGame/Arena/`(`ArenaRules` 탑·던전·투기장·적장 · `ArenaScreen`). 스탯 = §3-2 × (1 + 훈련(병종·항목)) × (1 + 보물(항목)) = `HeroRules.Compute(…, save)` · 보물 crit/range/splash = `BattleManager.SideEffectsProvider` → `SkillMods.Get` 진영 효과(`side_crit_pct` · `range_mult` · `splash_radius_mult`) · 조건 효과 카운터 = `Runtime/BattleEvents.Raise`(전투 코드 1줄씩 · 아군만) · 연무장 전투 = `BattleManager.StartMode(BattleMode)`(적 편성 · 제한 턴 · 결과 탭 = `onExit`) → `OutGameSession.OnModeEnd`. 테스트 = `Tests/PlayMode/OutGameCTests`. 캡처 = `-executeMethod TKS.EditorTools.DataImporter.CaptureC -cDir <dir>`(사본 · 10장).
- **영웅 56명(PD #1096 · 2026-11-06)** — heroes 71행(영웅 56 + 병사 15) · skills 112 · hero_gear 1344 · 신규 effect_key 4(`team_dmg_pct_turn` · `cooldown_add` · `charm` · `heal_self_pct`) + 기존 키 조건 열(받는 피해 p2 = HP 임계/2 보스/3 근접 · p3 = 출전 인원 아군 전원 · 최대 HP·반격 아군 전원 · 피해 % 발동 턴) = `SkillMods`·`SkillSystem` · 대장군 `pushed_ally_attack_on_push` 는 표에서 미사용(처리기 유지).
- **지형 기믹 레이어(PD #1097 · 2026-11-06 세션 D)** — SOT = `Assets/Data/Gimmicks/{gimmicks,stage_gimmicks,tutorial_tips}.csv`(기획 `tables/` 사본 · utf-8-sig) → 메뉴 `TKS/Import Gimmicks (기믹 임포트)`(`Editor/GimmickImporter` · 오류 시 자산 불변 · `ai_weights.csv` 도 함께) → `Resources/Gimmicks/GimmickDb`·`StageGimmickTable` · `Resources/AI/AiWeights`. 전투 시작 = `GimmickLayer.Build(stage)`(장-번호 배치 · 배경 위 · 유닛 아래 · 장애물 = 콜라이더 + `GimmickBody` · 지대 = 모양 스윕 · 강 콜라이더 = 다리 구간을 뺀 조각 · 겹친 유닛은 빈 자리로). 전투 코드는 질의만: `Combat.FreeTravel`(장애물 = 벽 · 숨은 함정 정지) · `FirstUnitOnArrow`(pass/block/destroy · 안개 제외) · `Combat.Damage`(군기 공 · 고지 근접 피격) · `SkillMods.Range`(고지 사거리) · `BattleManager` 턴 시작 `TurnStart`(군기·중독·불·행동 불가). 충돌 반응·폭발·굴림·미끄러짐·지대 = `Gimmicks/ActionResolver.Gimmicks.cs`(partial). 배치 도구 = `TKS/Gimmick Painter (기믹 배치)`. 테스트 = `Tests/PlayMode/GimmickTests` · 캡처 = `-executeMethod TKS.EditorTools.GimmickImporter.Capture -gimmickDir <dir>`(사본).
- **병종 규칙 개정 + 예측 AI(PD #1098 · 2026-11-06)** — 보병 = 적과 싸운 뒤 튕겨나는 길의 다른 적과 연쇄 교환 1회(`ActionOutcome.Chains`) · 창병 = 상대만 밀리고 자신은 × `spearRecoilRatio` 반대로(밀며 전진 폐기). 적 턴 = `Runtime/AI/TacticalAI`(후보 방위 × 파워 3 × 액티브 → `Sim` 가상 실행(연출 없음 · 분산 0 · 상태 복원) → `ai_weights.csv` 점수 · 서포터 → 돌격 → 사격 · 1기마다 재평가) · 가중치 자산이 없으면 `EnemyAI.Decide`(기존 조준) · 적 액티브 = 1부 보스만(`boss_active`). 가상 실행 중(`Sim.Active`)에는 `Fx`·`UnitView`·`BattleEvents`·HUD 갱신이 꺼진다 — 새 연출 코드도 `Sim.Active` 면 건너뛸 것. 조준 미리보기도 같은 가상 실행(`GimmickPreview` · 숨은 함정 모름). 테스트 = `Tests/PlayMode/TacticalAITests`.
- 아웃게임 코드 = `Assets/Scripts/OutGame/**`(asmref → TKS.Runtime) — `OutGameSession`(표 + 세이브 · 바꾸는 동작은 즉시 저장) · 규칙 `HeroRules`·`EconomyRules`·`GachaRules` · 화면 `UI/`(로비·영웅·편성·거래·결과 패널 · `OutGameRoot` 가 전환). 세이브 = `persistentDataPath/save.json`(테스트·검증 캡처는 `SaveStore.UseMemory` / SessionState `TKS_SAVE_MEMORY` 로 메모리 전용). 출전 = `BattleManager.LineupProvider`(편성 프리셋 → `playerSpawnPoints` 자리 0~2 전열 · 3~4 후열). 화면 캡처 = `Unity.exe -projectPath <사본> -executeMethod TKS.EditorTools.DataImporter.CaptureOutGame -outgameDir <dir>`.
- **챕터·스테이지 SOT = `Assets/Data/Stages/*.csv`(utf-8-sig · 2026-11-05 145 스테이지 · 기획서 #1086 §4 전사)** — `stages.csv`(chapter·stage·title·type normal|elite|boss·place·faction·병종 4 수·generals `id:병종:true|false`·bg_theme·note) · `chapters.csv`(장 제목·연도·**월드맵 맵 id**·AI 출발값) · `generals.csv`(무장 id → 이름·배율 덮어쓰기) · `factions.csv`(세력 코드 → 이름·병사 아트 접두). 고친 뒤 메뉴 `TKS/Import Stages (스테이지 임포트)`(`StageImporter` · 형식 오류면 자산 미변경) → `BalanceConfig.chapters·stages`. 적 좌표 = `BalanceConfig.formation` 규칙(전위·중군·후군·장수 줄 · `StageTable.Enemies`) · 장수 배율 = `generals.csv` 가 비면 `boss/eliteGeneral*Mult`. 월드맵 노드 = 스테이지 표(챕터별 수 · 보스 = type boss) · 노드 자리 = `ChapterMap/Data/<맵>.json` `slots_N`(없으면 길 위 균등).
- 규칙 해석 변경 = `Assets/Scripts/Runtime/ActionResolver.cs`(병종 4종) · `BattleManager.cs`(턴·승패·창병 대기) · `Combat.cs`(피해 공식·경로 질의). 변경 시 `Assets/Tests/PlayMode/BattleFlowTests.cs` 에 테스트 추가 후 22종 이상 전부 통과 확인.
- 콜라이더 질의 전 `Physics2D.SyncTransforms()` · 유닛 제거는 `SetActive(false)` 후 `Destroy` · 자식 렌더러가 있는 표시물은 GameObject 통째로 끈다.
- **궁병 규칙(PD 2026-11-04 · #1080)**: 사거리 = `slingMaxDistance`(얇은 원). 조준 방향 사거리 안의 적(가장자리 간격 기준) = **제자리 사격** · 사거리 밖 ~ ×(1 + `archerRangeRatio`)(붉은 도넛) 안의 적 = 들어올 만큼만(최대 `ArcherMoveAllow` = 슬링 × 비율) 다가가 사격 · 더 멀면 **목표점까지 이동만**(#1079). 반격 없음 · 목표점 명중 크리. **근접 전투**(돌진·반격·관통·견제·밀려 닿은 공격)에서 궁병은 근접 유닛 상대 주는 피해 × `archerMeleeDealtRatio`(0.5) · 받는 피해 × `archerMeleeTakenRatio`(1.5) — `Combat.Damage(…, melee)` · 원거리 사격은 패널티 없음.
- **충돌 규칙(PD 2026-11-04 · #1080)** — `ActionResolver`: 보병 = 경로 첫 유닛(아군·적군)에 부딪히면 **알까기**(등속 접근 → 부딪힌 순간 피해·반격을 즉시 교환(`ImpactExchange`) → **양쪽이 동시에 튕김**: 상대는 접촉 방향으로 남은 거리 × `collisionPushRatio` · 자신은 반대 방향으로 남은 거리 × `collisionSelfBounceRatio` · PD #1081) · 기병 = 유닛 무시 관통(적 피해 · 아군은 지나칠 거리가 안 나오면 **그 아군 직전 정지** `StopBeforeUnclearedAllies`) · 창병 = 첫 유닛을 **밀며 함께 전진**(접촉 간격 유지 · 앞 유닛이 막히면 둘 다 정지 · 적이면 피해 · 아군은 밀기만) · **규칙 ⑤** = 밀린 같은 진영 유닛이 상대와 닿으면(`Combat.TouchingOpponent` · 간격 ≤ 0.12) 그 자리에서 근접 공격 1회(조작마다 · 자기 행동 소모 없음 · `ActionOutcome.Notes`). 적 AI 도 같은 코드(대칭). `UnitStats.attackRange` 는 창병 견제 반경만.
- **사거리 표시(PD 2026-11-04)**: 유닛 탭(아군·적군) → `RangeIndicator`(슬링샷 최대 거리 = 얇은 반투명 원 · 궁병 = 슬링샷 범위 ~ ×(1+비율) 채워진 붉은 도넛 · 범위 안 적이 없으면 회색).
- 보고는 실측·추정·미확인을 분리한다(C23 · C5). 커밋은 의도 변경 파일만.
## 유닛 아트 반영 (다른 세션의 원화·애니 → 이 게임)
- 아트 위치 = `Assets/Resources/Units/<art>/<clip>/f000.png …` + `meta.json`(fps · ppu · pivot(발) · charHeightPx · clips). `<art>` 는 `BalanceConfig.asset` 의 `heroes[].art` / `stages[].enemies[].art`(비면 도형). 아군 = `liubei`·`guanyu`·`zhangfei`·`zhaoyun`·`huangzhong`(2026-11-04 재디자인 원화 · 스켈레탈 B단계 전까지 front_idle 정지 1장 · 납품 후 리그 v2 12 클립으로 교체) · 적 = `<세력>_<병종>`(`hgj_infantry` …) · 보스 = `<세력>_boss_<로마자>`(`hgj_boss_zhangjiao` …).
- 스켈레탈 리그 → 프레임: 조직 레포 스킬 `skeletal-anim-pipeline/files/scripts/rig_frames_export.py rig <리그 패키지> --parts <작업>/parts --out Assets/Resources/Units/<art> --clips back_idle,back_ready,back_action,back_damage,back_stop,front_idle,front_ready,front_action,front_damage,front_stop,front_victory,front_failed --px 180 --step 2`(ComfyUI venv python · 실측 482×470 · 15 fps · 3인 11 MB).
- 정지 그림(적 SD 전신 `_rgba.png`) → `rig_frames_export.py static <png> --out Assets/Resources/Units/<art>`(front_idle 1장 · 발 = 불투명 상자 아래). 원화 세션 납품 = `C:\ArtRnD\samguk_game\manifest.json` · 파일명 `<art>_rgba.png` → `<art>` 폴더(2026-11-04 1차 `hgj_*` 5종 + 2차 `dz_infantry·spear·cavalry·archer` 반영 완료 · 여포 `dz_boss_lvbu`·`cc_*`·`wei_*` 는 납품 시 같은 명령).
- 전장 배경 = `Assets/Resources/Board/<boardArt>.png`(자산 `boardArt` · 5:8 불투명 · PPU 100 = 전장 20×32) → `Board.Build` 가 있으면 바닥으로 쓰고 격자·진영 띠는 생략. 임포트 규칙(스프라이트 · 4096 · 압축)은 같은 `UnitArtImporter` 의 `Board/` 분기 · 재임포트 메뉴가 두 폴더 처리.
- 임포트 설정은 `Editor/UnitArtImporter.cs`(AssetPostprocessor · meta 의 pivot·ppu) 가 자동 적용 · 프레임을 넣거나 meta 를 바꾼 뒤 = 메뉴 `TKS/Reimport Unit Art`(Build/BuildFresh 가 함께 호출).
- 재생 = `UnitArt.cs`(Resources 로더 · 캐시) + `FrameAnimator`(대기 loop · 준비 = 조준 중 · 공격·피격 = 1프레임 자세 유지 후 대기 · 승리 = 끝 프레임 유지). **포즈 규칙(PD #1084 · 2026-11-05)**: 공격 애니 대신 1프레임 포즈 전환 — 조준(당기는) 중 = `ready`(출발 자세) · 슬링샷 이동(돌진) 중 = `action`(병종 돌진 포즈 · `UnitView.SetCharging` · `ActionResolver.Resolve` 가 루틴 전후로 켜고 끔) · 멈추면 `idle`. 돌진 중 피격은 색만 바뀜. **4방향 보기(PD #1082)**: `UnitView.SetFacing(dir)` — 마지막 이동 방향의 세로 성분으로 `back_*`(위 ↖↗) / `front_*`(아래 ↙↘) 세트를, 가로 성분으로 `flipX`(왼쪽 = 반전 · 오른쪽 = 기본)를 정한다. 시작 = 아군 ↗ · 적군 ↘. `ActionResolver.Face()` 가 이동·튕김·밀림·돌진·사격·밀린 아군 공격 때 호출(기병 복귀는 방향 유지). 없는 클립은 다른 보기 → 대기로 대체. 세로 크기 = `unitArtHeight`(자산) × 반지름 배율 · 발 = 원 중심 아래 0.55 R.
## 구조 (README 와 동일)
- `Assets/Scripts/Runtime/` — `GameBootstrap`(씬 구성) · `BattleManager` · `ActionResolver` · `Combat` · `SlingshotInput`(조작·스크롤·줌) · `RangeIndicator`(사거리 원·궁병 도넛) · `CameraController`(넓은 전장 카메라) · `EnemyAI`(교전 범위) · `BattleHUD`(HUD·미니맵) · `Unit`/`UnitView` · `UnitArt`(아트 로더·`FrameAnimator`) · `Board` · `Fx` · `AutoPlayDriver`
- `Assets/Scripts/Editor/` — `ProjectSetup`(CLI 진입점·씬 생성) · `BalanceDefaults`(최초 시드) · `StageImporter`(스테이지 표 → 자산) · `UnitArtImporter`(아트 임포트 설정) · `DataImporter`(아웃게임 표 → 자산 · 화면 캡처)
- `Assets/Scripts/OutGame/` — 아웃게임(세이브·로비·영웅·편성·거래·보상 · 내정 `Domestic/` · 보물 `Treasure/` · 연무장 `Arena/` · 위 「코드 규칙」)
- `Assets/Data/Stages/` — 챕터·스테이지 표 CSV 4장(위 「코드 규칙」) · 해석·배치 = `Runtime/StageTable`
- `Assets/Resources/Units/<art>/` — 유닛 아트 프레임 + meta.json(위 절)
- `Assets/Scripts/Runtime/Skills/` — 스킬 처리기(위 「코드 규칙」 스킬)
- `Assets/Scripts/Runtime/Gimmicks/` — 지형 기믹 레이어(위 「코드 규칙」) · `Assets/Scripts/Runtime/AI/` — 예측 시뮬레이션 적 AI(`Sim` · `TacticalAI` · `AiWeights`)
- `Assets/Data/Gimmicks/` · `Assets/Data/AI/` — 기믹 표 3장 · AI 가중치 표
- `Assets/Tests/PlayMode/` — `BattleFlowTests` · `OutGameTests` · `SkillTests` · `OutGameCTests` · `GimmickTests` · `TacticalAITests`
- `.claude/skills/` — Unity CLI 에이전트 스킬(`unity skill install claude-code --local` 산출물 · 재설치는 `unity skill refresh`)