ThreeKingdomsSlingshot/CLAUDE.md

29 KiB
Raw Blame History

삼국지 슬링샷 (가제) — 에이전트 작업 지침

너드나비스 조직 프로젝트 ⑤ (조직 레포 .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 · 원격 origin = https://burning.i234.me/NerdNavis_AiDev/ThreeKingdomsSlingshot.git(비공개 · 2026-11-09 · 다른 PC 와 함께 작업 = 시작 전 git pull · 커밋 후 git push). 미추적 = 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·paused)이어도 기다리지 말고 unity command --project-path . editor.playmode stop 으로 Play 를 중단 → stopped 확인 → 바로 작업한다(PD 지시 2026-11-04 · 2026-11-09 재확인 「내 PC 가 플레이 중이더라도 중단하고 작업해」 · 에디터 자체는 닫지 않음). 수정을 모두 끝낸 뒤 리컴파일 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 · 지대 = 모양 스윕 · 강 = 늪처럼 통과하는 지대(강 안 ×p3 · 다리 구간 = 효과 없음 · 강가·다리에서 밀려 강물에 들면 빠짐 · PD 2026-11-06 개정) · 겹친 유닛은 빈 자리로). 전투 코드는 질의만: Combat.FreeTravel(장애물 = 벽 · 숨은 함정 정지) · FirstUnitOnArrow(pass/block/destroy) · Combat.Damage(군기 공 · 고지 근접 피격 · 안개 원거리 피격 ×p1 · 책사 광역이 그 반경 안개를 걷음) · 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>. UI 수정 검증은 고친 화면만 찍는다(PD 2026-11-09 「매번 모든 화면 체크 = 시간·토큰 낭비」): Tools/mirror_verify.py → Unity.exe -projectPath E:/Nerdnavis/_tks_verify -force-d3d11 -executeMethod TKS.EditorTools.DataImporter.CaptureUI -uiDir <dir> -uiOnly hero_list,hero_detail*(이름 = 정확히 또는 「접두*」 · 다 찍으면 바로 종료 · 1장 ≈ 15초 · 전체 21장 ≈ 3분 · 이름 목록 = UICaptureDriver 의 Shot 이름).
  • 챕터·스테이지 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). 커밋은 의도 변경 파일만.

UI 캔버스·아틀라스 구조 (PD 2026-11-10 「리소스·정보가 얼마나 자주 바뀌는지에 따라 캔버스를 나누어 최적화 · 드로우콜 최소화 구조 필수」)

UI 를 새로 만들거나 고칠 때 반드시 이 구조를 따른다(어기면 Tests/PlayMode/UILayerTests 가 실패). 조직 전체 표준 = 조직 레포 프로젝트 규칙 P41(.claude/skills/너드나비스-코어룰/rules/P41.md · 2026-11-10) — 이 절은 그 표준의 이 프로젝트 구현 SOT 이자 다른 프로젝트의 참조 구현이다.

  • 갱신 등급 3단(Runtime/UI/UiLayer.cs UiRate): Static = 화면을 열 때만(바탕 · 틀 · 고정 글자) · Event = 조작·게임 사건 때(값 · 선택 · 턴 · 팝업) · Frame = 매 프레임(호흡 · 튀김 · 스크롤 내용 · 끌기 · 미니맵 · 커서). 등급이 다른 것은 같은 캔버스에 두지 않는다 — 캔버스는 자식 하나만 바뀌어도 그 캔버스 전체를 다시 묶는다.
  • 만드는 법: 루트 = UiLayer.Root(go, cam, order, plane, reference, rate) · 기존 오브젝트를 층으로 = UiLayer.Nest(go, rate, raycast) · 빈 층 = UiLayer.Group(name, parent, rate) · 매 프레임 요소 = UiLayer.Isolate(go)(UiPulse·UiPop 은 스스로 호출 · 바로 위 부모가 Frame 층이면 그 층에 합침). 중첩 캔버스는 overrideSorting 끔(그리는 순서 · RectMask2D/Mask 자르기 유지) · 누르는 그래픽이 있는 층에만 GraphicRaycaster(중첩 캔버스의 그래픽은 부모 캔버스 레이캐스터가 못 봄 → 누름 층은 raycast: true).
  • 현재 배치: 아웃게임 루트(Static · 바탕 + 하단 탭) → 화면마다 중첩(Event) → UiKit.ScrollGrid 내용(Frame · 자동) · 위 덮개 루트 → 재화 바 · 팝업(ModalCustom) · 토스트 · 뽑기 결과 · 편성 끌기 유령 각각 중첩 · 전투 결과 루트(Event · 별 줄 = Frame) · 전투 HUD 루트 = 정적 판(칩 바탕 · 유닛 판 바탕 · 미니맵 틀) → Info(글자·값·스킬 버튼 · Event) → Minimap/MinimapLive(시야·점 · Frame) · SkillGlow(Frame) → Result(Event) · 월드맵 루트(Static · 띠·넘김·본영) → Content(맵·노드 · 스크롤 · Frame) → cursor(Frame) · Popup(Event).
  • 매 프레임 호출되는 갱신 코드는 값이 같으면 쓰지 않는다(sizeDelta·anchoredPosition·CanvasGroup.alpha/interactable 비교 후 대입 · Text.text·Graphic.color 는 Unity 가 이미 비교).
  • 아틀라스: 구성 SOT = Assets/Data/UI/ui_atlas.csv(theme 줄 = UI 테마가 쓰는 스프라이트를 경로 match 로 · folder 줄 = 폴더 통째 · single_area 보다 큰 그림 = 묶지 않음) → Editor/UIAtlasBuilder → Assets/UI/Atlases/*.spriteatlasv2(UI_Common 4096×2048 · UI_Content 2048×2048 · WorldMap_UI 1024×1024 · 각 1장). UI 테마 임포트가 끝날 때마다 자동 갱신(새 납품 스프라이트 = 코드·표 변경 없이 묶임) · 수동 = 메뉴 TKS/Build UI Atlases (UI 아틀라스 갱신). 패커 = Sprite Atlas V2(에디터 Play 에서도 묶임 · EditorSettings m_SpritePackerMode 5). 사각 묶음(Tight 끔 · 회전 끔 — 9-slice·Filled 보존). 스프라이트를 잘라 새로 만드는 코드는 sprite.packed ? sprite.textureRect : sprite.rect(UISkin.WorldSprite 참고 · rect 는 원본 기준).
  • 검증: -executeMethod TKS.EditorTools.DataImporter.CaptureUI 캡처 로그에 화면마다 layers <화면> batches=… canvases=루트+중첩 … frameRebuildGraphics=… 줄 + ui_layers.csv(캔버스별 그래픽 수 · 등급 · 레이캐스터 · 매 프레임 요소 여부 · Runtime/UI/UiLayerProbe). 2026-11-10 개선 전→후(13화면 · 1080×1920) = 배치 합계 1124 → 439 · 평상시 매 프레임 재구성 그래픽(전투 HUD 49 → 10 · 월드맵 241 → 1 · 보물 상자 115 → 2 · 전투 결과 115 → 14).
  • 남은 드로우콜 원인(2026-11-10 실측): 영웅 목록(72)·편성(120) = 유닛 초상(유닛 아트 프레임 797×826 · 유닛마다 다른 텍스처라 카드마다 끊김) — 목록용 축소 초상 아틀라스 = 모든 영웅 리소스 제작이 끝난 뒤 진행(PD 2026-11-10 결정 · 그 전에는 만들지 않는다).
  • 같은 PC 의 다른 세션도 E:\Nerdnavis\_tks_verify 를 캡처에 쓴다 → 사본은 세션마다 따로(예 Tools/mirror_verify.py <본체> E:/Nerdnavis/_tks_verify_ui) · 남이 돌리는 사본에 미러하지 않는다(실행 중 코드가 바뀜).

스킬 이펙트 작업 (2026-11-09 PD 「WL 에서 스킬을 구현하던 방식과 동일하게 유닛별 스킬 구현」 · 이 PC = 연출 담당)

  • 스킬 테스트 씬 = Assets/Scenes/SkillTest.unity(메뉴 TKS/Skill Test/Build Scene 로 다시 만듦 · 씬 = SkillTestBootstrap 하나) — 전투 코드 그대로 + 월드맵·아웃게임·세이브 없음 · 왼쪽 위 「유닛 선택」(heroes.csv 영웅 56 · 진영별) · 「이펙트 보기」(에디터 전용 · Assets/VFX 프리팹 검색 → 고른 영웅 몸에 띄움 · 크기 ×0.25~4 · 기울기 0/−45/−90 · 방향 · 경로 복사) · 왼쪽 아래 「다시 배치」(표 다시 읽기 + 처음 자리) · 쿨 무시 · 더미 행동 · 영웅 무적. 더미 = 죽지 않음(Unit.Invincible · 아군 턴마다 체력 회복) · 배치 표 Resources/Skills/skill_test.csv(hero 행 n_slot + 상대 좌표) · 더미 행동 끔 = BattleManager.EnemyHold. 패널 위 누름은 슬링샷이 무시(SlingshotInput.BlockPress).
  • 이펙트 값 = 표 Assets/Resources/Skills/skill_vfx.csv(머리 주석이 칸 설명) → Runtime/Skills/SkillVfx(전투마다 다시 읽음). 키 = 스킬 id(액티브) 또는 basic_<병종>(일반 슬링샷 공격 · 이동만인 추가 이동 제외) · 이벤트 = cast(발동) · travel(슬링샷 돌진 동안 · f_every 반복) · hit(그 행동의 피해 순간 · 대상마다 1번). 훅 = SkillSystem.Announce(cast) · BeginAction/EndAction(travel) · Hit(hit) · 즉시형 Instant. 크기 f_scale = 유닛 키 대비(WL 배율 ÷ 1.8 ≈ 같은 비율) · 입자 크기 모드는 띄울 때 전부 Hierarchy · 정렬 = 12 + n_order · 가상 실행(Sim) 중 없음.
  • 이펙트 사본 규칙(WL WL_Fx_* 와 같음): 게임이 읽는 것 = Assets/Resources/Fx/TKS_Fx_<이름>.prefab 사본만(메뉴 TKS/VFX/Make Skill Fx Copy · 고른 프리팹 → 사본) · 원본 팩 Assets/VFX/** 는 고치지 않는다.
  • WL 리소스 옮기기 = Tools/wl_vfx_import.py(scan · copy · unpack · --wl <WL 루트> · GUID 유지 · URP 전용 셰이더 재질 프리팹은 자동 제외 · WL 원본 무수정) → 에디터 새로고침 → 메뉴 TKS/VFX/Check Imported VFX(분홍 재질 · 빠진 스크립트). 판정 표 = Assets/VFX/_wl_import_report.csv. 2026-11-09 옮긴 것 = VFX_Klaus(Hyper Casual 1·2 · Shoot&Hit 1·2 · Earth Skills · Element Splash 3) · Lana Casual RPG VFX · Slash Effects FREE · EricWang 4묶음 중 빌트인 통과분 · MasterStylizedProjectiles 통과분 · Kyeoms 폭발 · GAP 툰 투사체(빌트인 패키지 unpack) · WL 창 돌진 사본 3(Assets/VFX/WL/) = 약 640 MB.
  • URP 셰이더 이식판 = Assets/VFX/_BuiltinPorts/*.shader(원본과 같은 GUID · 셰이더 이름 · 속성 → 옮겨 온 재질이 그대로 사용 · 현재 Eric AdditiveFlow · AlphaBlendFlow · MasterStylizedFX EmissiveParticle · CommonMesh2Side). 새로 필요한 URP 셰이더는 같은 방식으로 이식하면 wl_vfx_import.py 가 통과(port)로 본다.
  • 카메라 깊이 텍스처 켬(GameBootstrap · SkillTestBootstrap depthTextureMode |= Depth): Hyper Casual 등 셰이더 그래프의 소프트 파티클이 _CameraDepthTexture 를 읽음 — 없으면 이펙트가 안 보이거나 불투명 하늘색 덩어리(2026-11-09 실측). 셰이더 그래프 재질은 com.unity.shadergraph 17.3.0(Built-In 타깃) 필요.

유닛 아트 반영 (다른 세션의 원화·애니 → 이 게임)

  • 아트 위치 = 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 · UILayerTests(캔버스 층·아틀라스 구조 · 2026-11-10 · 전체 119)
  • .claude/skills/ — Unity CLI 에이전트 스킬(unity skill install claude-code --local 산출물 · 재설치는 unity skill refresh)