--- type: 설계문서 project: 수상한잡화점 subject: 독립 시뮬레이터 아키텍처 (Unity MCP 실행 인프라) version: v1 date: 2026-04-17 status: 초판 author: 개발팀장 related: - 공유/소통/개발팀→PM/2026-04-17_Phase0-C_QP2_정밀2차_응답서.md - 프로젝트/수상한잡화점/시뮬레이터/02_시나리오_JSON_스키마_v1.md - 프로젝트/수상한잡화점/시뮬레이터/03_결과_JSON_포맷_v1.md - 프로젝트/수상한잡화점/시뮬레이터/04_MCP_호출_스니펫_v1.md 핵심원칙: - 기존 수상한잡화점 코드 일체 수정 금지 - 독립 어셈블리 격리 (`BurningTimes.Sim.asmdef`) - Editor-only (빌드 산출물 제외) - 메커닉은 별도 모델로 독립 재구현 (Read-only 참조) --- # 독립 시뮬레이터 아키텍처 v1 ## 1. 배경 (왜 필요한가) ### 1-1. PD님 직접 지시 (2026-04-17) > "기존 수상한잡화점 프로젝트의 코드나 구조에 영향을 주지 않는 독립적인 시뮬레이터로 동작해야 함." ### 1-2. 요구사항 해석 1. **기존 코드 불변 원칙**: `Assets/Script/` 하위 파일을 일절 수정 불가. 시뮬 인프라는 **관찰·참조**만 허용, **수정·확장·상속**을 통한 침투 불허 2. **독립 어셈블리 격리**: 기존 `Assets/Script/*.asmdef`와 별개 어셈블리로 운영하여 빌드 의존성·컴파일 영향 차단 3. **Editor-only 동작**: 프로덕션 빌드 산출물에 시뮬 코드 포함 방지 (앱 크기·보안·의도치 않은 실행 차단) 4. **메커닉 재현의 독립성**: Actor·Effect 등의 로직을 재사용·복제가 아닌 **동등 결과를 내는 별도 로직**으로 독립 재구현 ### 1-3. 설계 제약 (대안 고려) - **대안 A (기각)**: 기존 `Assets/Script/Actor/` 직접 호출하여 시뮬 실행 → 코드 수정 위험·PlayMode 의존·PD 제약 위반 - **대안 B (기각)**: 별도 레포 구축 → Unity MCP `execute_code`가 현 프로젝트 내부만 접근 가능, 운영 분리 과도 - **대안 C (채택)**: 같은 Unity 프로젝트 내 `Assets/Sim/` 신규 폴더 + 독립 asmdef + Editor-only define + 모델 독립 재구현 --- ## 2. 폴더·어셈블리 구조 ``` D:/BurningTimes/FilGoodBandits/DeckBuilding/Assets/Sim/ ← 신규 (이번에 생성) ├── BurningTimes.Sim.asmdef ← 독립 어셈블리 정의 ├── Runtime/ │ ├── SimulationRunner.cs ← 진입점 │ ├── ScenarioLoader.cs ← 시나리오 JSON → ActorModel 로드 │ ├── ResultEmitter.cs ← 결과 JSON 출력 │ └── Models/ │ ├── ActorModel.cs ← Actor 동등 모델 (독립 재구현) │ ├── DefenceModel.cs ← 터치 방어 30% + 지속형 재현 │ └── DamageCalc.cs ← 데미지 감소 pipeline 재현 ``` ### 2-1. 어셈블리 정의 (`BurningTimes.Sim.asmdef`) - `name`: `BurningTimes.Sim` - `rootNamespace`: `BurningTimes.Sim` - `references`: **비움** (기존 어셈블리 참조 안 함 — 독립성 확보) - `includePlatforms`: `["Editor"]` (Editor-only) - `excludePlatforms`: `[]` - `autoReferenced`: `false` - `defineConstraints`: `["UNITY_EDITOR"]` - `noEngineReferences`: `false` (UnityEngine은 사용, but 최소) ### 2-2. 의존성 격리 결과 - 빌드 시 본 어셈블리 **자동 제외** (Editor 플랫폼만 타겟) - 기존 게임 어셈블리와 컴파일 단위 분리 → 기존 코드 변경 감지 없음 - 기존 `Assets/Script/` 전혀 참조하지 않으므로 기존 리팩토링·삭제에도 영향 없음 --- ## 3. 실행 흐름 ``` 기획팀장 Unity MCP SimulationRunner │ │ │ │ 04_MCP_호출_스니펫_v1.md 기반 │ │ │ execute_code 호출 │ │ │ {scenario_json_path: "..."} │ │ │ │ │ │ ─────────────────────────────► │ │ │ │ │ │ │ SimulationRunner.Run(path) │ │ ─────────────────────────► │ │ │ │ │ │ 1. ScenarioLoader.Load(path) │ │ │ → ActorModel 생성 │ │ │ 2. 전투 tick 루프 실행 │ │ │ (DefenceModel·DamageCalc 호출) │ │ │ 3. ResultEmitter.Emit(result) │ │ │ → 결과 JSON 파일 또는 stdout │ │ │ │ │ ◄───────────────────────── │ │ {결과 JSON} │ ◄───────────────────────────── │ │ │ │ │ 기획팀 분석·밸런스 튜닝 │ │ ``` ### 3-1. 실행 환경 2모드 - **모드 1 (단일 실행)**: Unity Editor 기동 상태 + MCP 연결 + `execute_code` 한 번 → 결과 1건 - **모드 2 (배치 실행)**: `execute_code`로 스윕 파라미터 배열 전달 → 내부 루프로 N회 실행 + 결과 N건 집계 --- ## 4. 독립 모델 설계 (Models/) ### 4-1. ActorModel **기존 `Actor.cs`(4545줄)를 재구현하지 않는다.** 시뮬에 필요한 최소 상태만 추출: ```csharp public class ActorModel { public string id; public float maxHP, hp; public float shield; public float attackDmg; public float attackCoolTime; public float accumulatedAttackTime; public bool isDefencing; // ActorStatus == Defecne 동등 public bool isDead => hp <= 0f; // ... 시뮬 범위 내 최소 필드만 } ``` ### 4-2. DefenceModel (실측 규칙 재현) Q-P2 정밀 2차 응답서 §2 실측 기반 독립 구현: - `PCDefence_Mul = 0.3f` (30% 감소) - `PCDefence = 1` (절대값 1 감소) - 터치 Down↔Up 지속 (`isDefencing` 플래그) - 방어 중 공격 불가 (`accumulatedAttackTime` 갱신 중단) - 방어 중 데미지: `dmg = (dmg - 1) * (1 - 0.3)` (추가 감소 스택은 포함하지 않음 — 단순화) ### 4-3. DamageCalc (감소 pipeline 재현) `Actor.cs:762-809` 실측 기반 간이 재구현. 시뮬 범위 외(카드·인장·각성)는 제외하고 **순수 방어 메커닉 + 기본 스탯** 차원만 재현. 복잡 메커닉 필요 시 scope 확장 v2에서 추가. ### 4-4. 재구현 원칙 - **동등 결과 우선, 구조 복사 금지** — 기존 코드를 복붙하지 않고 실측 스펙을 문서로 보고 재작성 - **최소 기능 원칙** — 밸런싱에 필요한 축(HP·Shield·Dmg·Defence·CoolTime)만 구현, 나머지는 생략 - **버전 고정 주석** — 각 파일 상단에 `// 실측 기준: Dev 브랜치 43b6074c4 (2026-04-17)` 명시하여 원본 변경 시 재동기화 시점 명확화 --- ## 5. 검증 방법 ### 5-1. 기존 코드 불변 증명 - 본 작업 커밋 diff에 `Assets/Script/` 하위 변경이 **0건**이어야 한다 - `git diff --stat Assets/Script/` 결과가 비어있는지 확인 ### 5-2. 빌드 제외 증명 - `manage_build` MCP로 Player 빌드 시도 → 빌드 로그에 `BurningTimes.Sim` 미포함 확인 - `BurningTimes.Sim.asmdef`의 `includePlatforms: ["Editor"]` 준수 ### 5-3. 메커닉 등가성 검증 (향후) - 동일 시나리오에서 실제 게임 PlayMode vs 시뮬 실행 결과를 **기획팀이 비교** → 오차 10% 이내 목표 - 오차 원인이 시뮬 모델 누락인지 실측 데이터 누락인지 구분하여 보완 ### 5-4. MCP 연결 필요 환경 - 본 세션에서 **Unity MCP 접근 가능 여부 미확인** (C23 정직: `mcp__unity-mcp__*` 호출을 실제로 수행하지 않음). 스켈레톤 코드는 작성 완료 상태이며, Unity Editor 구동 + MCP 연결 시점에 기획팀장·개발팀이 실행 검증 --- ## 6. 확장 포인트 (v2 이후) 1. **카드·인장·각성 효과 모델 추가** — 현재 스코프는 방어 메커닉 중심. 기획팀이 밸런싱 축 확장 요청 시 Models/에 파일 추가 2. **몬스터 AI 모델** — 현재 단순 공격 tick만. 라인별 공격 조건·특수 효과(자폭·치명타 등) 재현 필요 시 `MonsterAIModel.cs` 추가 3. **앵커 전투 노드 시퀀스 통합** — 단일 전투가 아닌 스테이지 경로 전체 시뮬 --- ## 7. 변경 이력 - **v1 (2026-04-17)**: 초판. PD 지시 #37 독립 시뮬 제약에 따른 어셈블리 격리 아키텍처. ## 8. 기각안 (P24) - **기각안 A**: `AssemblyDefinitionReferences` 로 기존 `Assets/Script/` 어셈블리 참조 → 독립성 훼손, PD 제약 위반. 0 references 고수 - **기각안 B**: Runtime 포함(Editor-only 제외) → 빌드 산출물 오염·보안. Editor-only 확정 - **기각안 C**: `Assets/Editor/Sim/` 아래 배치 → Unity asmdef 자동 Editor 어셈블리와 충돌 위험. `Assets/Sim/Runtime/` + 자체 asmdef의 Editor 플랫폼 제약이 깔끔 - **기각안 D**: 별도 레포 서브모듈 → Unity MCP `execute_code` 경로 접근 제약·기획팀 셋업 복잡도 증가. 동일 레포 격리가 최선