diff --git a/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md b/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md index ca16eaa..fc8c06d 100644 --- a/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md +++ b/공유/PD_지시_트래킹/개발팀_PD_지시_로그.md @@ -33,6 +33,7 @@ C3·C13 위반에 해당. **즉시 자진 보고 후 소급 등록**. | # | 일시 | 지시 요지 | 처리 상태 | 산출물 경로 | 중단 사유 | 사후 조치 | |---|------|----------|----------|-----------|----------|----------| +| BT12-Dev-Clone | 2026-05-15 22:00 | **A10 분신 스킬 구현 (C43 호칭 + C49 시범)** — PD 직접 발화 (2026-05-15): "이번에는 분신 스킬을 구현해줘. 이 스킬을 사용하면 플레이어의 x좌표 1 뒤쪽에 반투명한 형태의 플레이어의 분신이 생성되어서 플레이와 동일한 스킬을 사용해야 해. (단, 분신의 공격은 플레이어의 공격력의 50% 반감되어야하고, 플레이어보다 0.5초 뒤 사용해야 해. 공격 시작 딜레이)". A10 = BT12-Dev 미구현 8종 중 1. BT12-Dev 보류 와중 PD 명세 확정 부분 구현. C49 시범 (개발팀장 Opus 설계 → 클라이언트팀 Sonnet 구현 → 개발팀장 검증). **PM 1차 합리적 기본값**: facing 반대 1유닛·alpha 0.5·lifetime 영구 1기 (새 발동 시 기존 대체)·무적 유지 (v0.4 CSV "분신은 무적이나 공격력 비율 감소" 정합)·collision 무충돌·Lv 업 1차 미반영 (후속 안건) **[1단계 완료 2026-05-15 16:56]** 개발팀장 Opus 직접 설계 — `프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md §A10` 신설 (16 sub-section · 약 320 라인). 구조 결정 = (나) CloneInstance MonoBehaviour + 0.5초 지연 큐 + IsCloneFireActive 분기 (옵션 (가)·(다) 기각근거 명시). 신규 파일 2 + 수정 9 + asset 1 + 테스트 1 = 13 영역 작업 단위 분해. 기각안 5건 (별도 Inventory mirror·Effector 2회 발동·transform swap·8초 lifetime·독립 facing). EditMode 7건 신설 안. PD 결정 안건 3종 (BaseCooldown 30·facing 변경 시 위치·무적 spec). 스킬 이펙트 확정 SOT §3 A10 추가 (BaseCooldown 30·BaseDamage 0·Lifetime 영구·코드 하드코딩 영역 명시) + §4 변경 이력 갱신. | **진행중** | **1단계 완료** — 설계 문서 §A10·이펙트 SOT §3 A10·변경 이력 갱신 완결. **2단계 진행 영역** — 클라이언트팀 Sonnet Task 위임 영역 (신규 4 파일·수정 9 파일·asset 1·테스트 1·약 60~80K 추정). C50 영역 본 Task 누적 약 25K + 2단계 위임 약 60K + 3단계 검증 약 15K = 약 100K. C50 사전 PD 안내 영역 외 자체 판단 — PD 매니페스트 등록 시 인지 영역. | — | 2단계 결과 수령 후 3단계 개발팀장 검증 (C49 표준 프로세스 시범 영역) + PM 보고. **모호 영역 PD 결정 안건** (3단계 검증 보고 명시): (1) BaseCooldown 30 PM 추정 — balance-designer 후속 확정 (2) facing 변경 시 분신 위치 (spawn 시점 고정 vs Player 추종 동조) (3) 분신 무적 = 시각 GameObject 자체 (collider 미부착) — 적이 분신 위 올라타거나 적 투사체 통과 영역 Play 검증 (4) Lv 업 (분신 수 증가 등) 1차 미반영 영역 후속. **[BT12-Dev-Clone 완전 완료 2026-05-18]** α·β·γ·δ 4단계 전수 완료. **α**: CloneInstance.cs (218 라인)·CloneEffector.cs (24 라인) 신규. **β**: PlayerSkillInventory (필드 5종+이벤트)·ActiveSkillRuntime (Fire OnPlayerSkillFired·CalculateEffectiveDamage 50% multiplier)·SkillFireEvent (Minion CardId 분기·Cleanup reset)·SkillRuntimeFactory (A10 추가) 수정 4. **γ**: PlayerSkillInventory.GetSpawnAnchor·GetSpawnFacing helper 2 신설 + 6 Effector (Projectile·Laser·MeleeArea·LightningStrike·PoisonSwamp·SpiritFire) anchor·facing 분기 일관 적용. **δ**: A10_bunsin.asset (CardId A10·BaseCooldown 25·MinionLifetime 12·Category Minion) + CloneSkillTests.cs (EditMode 7건·PD 상수·multiplier·helper·Singleton·재귀 skip 검증) 신규. EerieVillage local commit `171506e` (18 파일 변경·PD Editor GitAutoSync 자동 push 대기·burning.i234.me origin 인증). 설계 v1 §A10 잔존 5 위치 (1423·1427·1431·1524·1572) PD 결정 정합 정리 완료. **[PD 결정 4건 2026-05-15 본 응답]** (1) BaseCooldown **25초** (PM 1차 30→PD 25) (2) MinionLifetime **12초** (PM 1차 영구 1기→PD 12초 자동 소멸·Singleton 유지) (3) facing 고정 확정 (4) 무적 Collider 미부착 확정 (5) Lv 업 시 분신 수 X·추후 지속시간↑+플레이어 참조 데미지 비율(%)↑ (balance-designer 후속 수치). SOT 설계 v1 §A10-1·이펙트 SOT v1 §3 A10·§4 변경 이력 PD 결정 반영 완료. **2단계 진행**: PM 권고 (b) 4분할 채택 — α CloneInstance·CloneEffector 신규 → β Inventory·Runtime·Event·Factory 수정 → γ 6 Effector → δ asset+EditMode | | BT12-Dev-Vis | 2026-05-09 | **PlayerSkillInventory 등록 시각화 지시** — PD 직접 발화: "PlayerSkillInventory 등록이 되었는지 어떻게 판단해야하지? 시각적인 변화가 없으니 확인이 불가능해. 유니티 기본 제공 리소스를 활용해도 좋으니 보이게 해줘." **[2026-05-13 후속 세션 신규 3건]** (1) 투사체 사거리 파란 박스 시각화 — `HitboxDebug.SpawnRange` 신규 (`Projectile.Initialize` 끝 호출·3초 유지·`HideFlags.DontSave`). (2) 사정거리·속도 Inspector 직접 조절 — `ActiveSkillData.MaxRange`·`ProjectileSpeed` 신규 필드 (`RangeTier`·`camWidth`·`mults` 계산 폐기·`PiercingProjectile._speed = 2.5f` override 폐기). (3) A04 ExtraHitFxPrefab + FX_Thunder Smoke — `ActiveSkillData.ExtraHitFxPrefab` 신규·`LightningStrikeSpawner.DelayedExtraHitFx` Coroutine (0.6초 후 spawn·y -0.5·비주얼 전용·판정 무관). EerieVillage `ab40b27` push 정합. **[2026-05-13 사고 정정]** 본 PM `git reset --hard origin/main` 영역 PD Inspector 작업 .asset 6 폐기 사고 발생. PD 보고 "스킬 관련 스크립터블 오브젝트가 full 이후 롤백되어버렸어" 수령. `git reflog` 영역 `e2bc95f` 보존 정합·.asset 6 복구·EerieVillage `5b2a032` push 정합. A04 ExtraHitFxPrefab (FX_Thunder Smoke) 영역 PD 후속 Inspector drag&drop 필요. 본 PM 자성 #4 (헌법급) 등재. **[2026-05-13 신규 2건]** (1) 디버그 박스·사거리 박스 시각화 off (재활용 toggle) — `HitboxDebug.ShowDebugVisuals` 플래그 신규·4 위치 `SpriteRenderer.enabled` 정합. (2) 레벨업 카드 풀 5종 한정 — `SkillRuntimeFactory.AvailableCardIds` 화이트리스트 (A02·A13·A04·A05·A_Laser)·미완성 placeholder 5종 (A01·A03·A08·A14·A15) 제외. EerieVillage `d26bd83` push 정합. **잔여**: A04·A05·A_Laser 영역 SkillFireEvent default return 영역 실전 발사 미연결 (카드 풀 한정 영역과 별개·PD 후속 결정 대기). **[2026-05-13 정정·진단]** (1) A05·A_Laser 박스 시각 off 누락 정정 — MeleeAreaSpawner·LaserSpawner 영역 직접 SpriteRenderer 부착 코드 (HitboxDebug 미경유) 영역 `sr.enabled = HitboxDebug.ShowDebugVisuals` 추가. 본 PM 자성 #5 (변경 영향 사전 grep 누락). (2) Player 피격 X 진단 Debug.Log 추가 (회수 의무) — EnemyController.Update L387-396 영역 `[EnemyHit][Intersect]`·`[EnemyHit][Decrement]` 2종. PD Console 측정 결과 영역 근본 fix·Debug.Log revert. EerieVillage `e8779df` push 정합. **[2026-05-13 신규]** 게임 시작 시 기본 파이어볼 A02 자동 습득 — `PlayerSkillInventory.StartingCardIds` (string[]) Inspector 필드·기본 `{ "A02" }`·`Start()` 영역 일괄 `AddSkillByCardId`. EerieVillage `0ad1325` push 정합. **[2026-05-13 신규 2건]** (1) Player 피격 X fix — EnemyController.Update L387-396 영역 `IsGrounded` 조건 폐기 (PD 표현 "닿아도" = ground·공중 무관 피격 의도)·진단 Debug.Log 2종 revert. (2) Enemy HP 30~40 random — `Health.RandomMaxHPRange` (Vector2Int) Inspector 필드 신규·Awake 영역 random·`maxHearts` 자동 산정·Enemy.prefab Inspector `(30, 40)` PD 직접 설정. 본 PM 자성 #6 (PD Console 측정 결과 미수신 영역 가설 fix 시도·feedback_pm_root_diagnosis_priority 약한 위반). EerieVillage `b4847b1` push 정합. **[2026-05-13 재발 정정]** (1) Enemy HP 30~40 자동 fallback — Health.Awake 영역 RandomMaxHPRange 미설정 + EnemyController 검출 → 자동 random. PD Inspector 의존 폐기. (2) Player 피격 distance 기반 강화 + 진단 Debug.Log 재추가 — `VisualBounds.Intersects OR dist < 1.5f` 단일 조건·`[EnemyHit]` 진단·회수 의무. 본 PM 자성 #7 (feedback_pm_root_diagnosis_priority 위반 누적). EerieVillage `2efcd34` push 정합. **[2026-05-13 신규]** Enemy·Player 사망 모션 y -0.5 오프셋 — EnemyDeath·PlayerDeath Execute 영역 Animator death/hurt Trigger 직전 `transform.position.y -= 0.5` 적용·sprite 위로 떠 보이는 현상 정정·collider 영향 X. EerieVillage `18b2125` push 정합. **[2026-05-13 신규]** 스킬 선택 UI 아이콘 fallback — SkillCardSlot.Bind 영역 card.Icon null 시 동적 원 sprite (32×32 알파) + 속성별 색상 (Fire 주황·Frost 하늘·Dark 보라·Lightning 노랑·Physical 흰). _glowEffect 동심원 빛 효과 alpha 0.3. EerieVillage `32ab76f` push 정합. **[2026-05-13 신규 2건]** (1) 사망 모션 y -0.5 → -0.3 (EnemyDeath·PlayerDeath). (2) 게임 시작 시 파이어볼 투사체 정지·잔존 fix — ProjectileSpawner.Trigger 영역 `facing.sqrMagnitude<0.01f` 시 `Vector2.right` fallback. 원인: Player.Facing 영역 (0,0) 영역 → _direction = (0,0) → _speed × 0 = 정지. EerieVillage `56a4a36` push 정합. **[2026-05-13 신규]** 투사체끼리 통과 fix — Projectile.OnTriggerEnter2D 영역 동족 Projectile skip (Wall·Enemy 판정 이전). 원인: fallback GO default Layer 0 영역 → isWall=true → 양쪽 SelfDestruct. EerieVillage `ebd7086` push 정합. **[2026-05-13 신규 4건]** (1) Player 사망 사라지는 현상 fix — PlayerDeath 영역 `Rigidbody2D.simulated=false` (gravity 정지·낙사 차단). (2·3) 제자리 부활·부활 모션·2초 무적 깜박 — PlayerSpawn 영역 `Teleport` 폐기·`health.Resurrect()` 호출 (currentHP=maxHP·invulnerableUntil=2초·Animator resurrect Trigger)·Rigidbody simulated=true 복원·PlayerInvulnerabilityFlash 자동 깜박. (4) FX 잔상 safety cap 5초 — LaserSpawner fx Destroy 누락 추가·LightningStrike·MeleeArea·Projectile.AutoDestroy 영역 `Mathf.Min(lifetime, 5f)` cap. EerieVillage `3a672f0` push 정합. **[2026-05-13 컴파일 에러 fix]** PlayerSpawn.cs CS0246 — using UnityEngine 누락·첫 줄 추가. 본 PM 자성 #8 (신규 type 사용 시 namespace using 사전 검증 누락). EerieVillage `c052d78` push 정합. **[2026-05-13 신규 3건]** (1) Player 죽는 모션 X fix — Player.controller parameter "hurt" 부재 측정·`SetTrigger("hit")`·`updateMode=UnscaledTime`. (2) 부활 모션 중 움직임 fix — PlayerSpawn simulated 복원 폐기·EnablePlayerInput 영역 이전. (3) 투사체 잔상 진단 — `[Projectile][SelfDestruct]`·`[Projectile][OnDestroy]` Debug.Log·회수 의무. 본 PM 자성 #9 (Animator parameter 사전 측정 누락). EerieVillage `69a1805` push 정합. **[2026-05-13 NullReferenceException + 잔존 근본 fix]** ProjectileSpawner.Trigger 영역 collider isTrigger=true 활성 시점 vs Initialize 호출 시점 race → OnTriggerEnter2D 영역 `_runtime=null` NullReferenceException → SelfDestruct 미호출 → 영구 잔존. fix: OnTriggerEnter2D 영역 `_runtime/_data == null` defensive return + Update 영역 `_data == null` 시 즉시 SelfDestruct. 본 PM 자성 #10 (race condition 사전 측정 누락). EerieVillage `1437720` push 정합. **[2026-05-13 신규 3건]** (1) 사망 팝업 타이밍 fix — LevelUpManager.HandleLevelUp 영역 Player 사망 상태 시 _pendingLevels 영역 저장·Update 영역 IsAlive 회복 시 표시. (2) Player 사망 y -0.3 추가 (누적 -0.6). (3) 투사체 잔상 강화 + 진단 — Projectile.Update 영역 lifetime+0.5 backup·Initialize·Trigger 영역 진단 Log·회수 의무. EerieVillage `b1931af` push 정합. **[2026-05-13 근본 원인 fix]** 재시작 시 정지 투사체 누적 — Time.timeScale=0 (LevelUp 등) 영역 Time.time·Invoke 정지 영역 영구 잔존. fix: Projectile `_spawnTime = Time.unscaledTime`·Update 영역 unscaledTime lifetime check·Invoke 폐기·CancelInvoke 추가 안전. 본 PM 자성 #11 (timeScale 영향 사전 측정 누락). EerieVillage `705d943` push 정합. **[2026-05-13 진단 Log 회수]** PD "사라졌어" 정합 작동 확인 후 진단 Debug.Log 5종 revert (ProjectileSpawner·Projectile.Initialize·SelfDestruct·OnDestroy·EnemyHit). Projectile.Update lifetime backup·CancelInvoke 안전망 보존. feedback_pm_root_diagnosis_priority 정합. EerieVillage `41fa4e4` push 정합. **[2026-05-13 신규 2건]** (1) MeleeArea 실전 발사 연결 — SkillFireEvent.Execute switch 영역 MeleeArea case·CardId 분기 (A04·A_Laser·기타). (2) FX AutoDestroy unscaledTime — FxAutoDestroyUnscaled MonoBehaviour 신규 (Object.Destroy 영역 timeScale 영향 fix)·전수 변경·WaitForSecondsRealtime. 본 PM 자성 #12 (Unity 표준 API timeScale 영향 사전 측정 누락). EerieVillage `26b0666` push 정합. **[2026-05-13 신규]** A04 번개 충격 적 유무 무관 자동 발동 — LightningStrikeSpawner.Trigger 영역 candidates 0 시 Player 위치 fallback spawn. A05·A_Laser = 이미 Player 위치 기준 발동·정합. EerieVillage `ebedf6d` push 정합. **[2026-05-13 InvalidOperationException Input System fix]** ParticleGroupView (2).cs 영역 삭제 (Scenes 폴더 영역 비정상 .cs·미사용·StandaloneInputModule 동적 부착 코드)·ProjectSettings activeInputHandler 1→2 (Both 모드·호환). 본 PM 자성 #13. EerieVillage `b30976a` push 정합. **[2026-05-13 본 PM 자성 #14 + fix 정정]** PD 직접 자성 지적 — 본 PM 직전 미승인 `.cs` 삭제 영역 정정. PD 재배치 후 ParticleGroupView (2).cs UnityEngine.Input → InputSystem 전환·activeInputHandler 2→1 revert. EerieVillage `b23e00f` push 정합. **[2026-05-13 Phase A]** A12 정화의 빛 신규·A08 저주의 화살 이펙트 적용 — ActiveSkillData.CastFxPrefab 신규·ProjectileSpawner.Trigger 영역 CastFx spawn·SkillRuntimeFactory.AvailableCardIds 7종 확장. **Phase B 대기** (A06 독 늪·A11 정령불 신규 Effector). EerieVillage `5077f5d` push 정합. **[2026-05-13 Phase B]** A06 독 늪·A11 정령불 신규 Effector + 1키·2키 매핑 — PoisonSwampSpawner/Instance/PoisonedEnemyMarker·SpiritFireSpawner/Instance 신규·SkillFireEvent switch PlacementPersistent·Minion case 확장·TestSkillFireOn1to5 Category 분기 추가·A06·A11 .asset 신규·SkillRuntimeFactory 9종. PD Inspector Player.prefab Skill1·Skill2 drag&drop 필요. EerieVillage `f292eb4` push 정합. **[2026-05-13 Phase B FX 재생 fix]** ParticleSystem 명시 `Play(true)` 호출 추가·PoisonSwampInstance 영역 BoxCollider2D·Rigidbody2D 자식 GO 분리 (ParticleSystem root 영향 차단). EerieVillage `b1b476a` push 정합. **[2026-05-13 A11 frame 제어]** FX_Rotating shield Animator frame 제어 — intro 1~88·loop 89~105 반복·outro 106~169 (남은 frame). Animator.Play(STATE_HASH, 0, normalizedTime) 매 frame 호출. EerieVillage `ebd0808` push 정합. **[2026-05-13 A12·A08·전수 FX Play]** 4 Spawner + Projectile 영역 ParticleSystem.Play(true) 명시 호출 전수 적용 (직전 b1b476a 영역 PoisonSwamp·SpiritFire만 적용 영역 영역 영역 보완). EerieVillage `68843a8` push 정합. **[2026-05-13 A08 sprite 방향 fix]** ActiveSkillData.ProjectileAngleOffset (float Range -360~360) 신규·Projectile.Initialize 영역 angle 보정·A08.asset 180 (FX_PinkMagicArrow sprite left→right). EerieVillage `71c3b7d` push 정합. **[2026-05-13 A08 FX 진단]** A08.asset GUID 정합·코드 정합 측정. PD 보고 영역 실측 진단 Debug.Log 추가 (회수 의무). EerieVillage `aa6cef1` push 정합. **[2026-05-13 CS1056 fix]** ProjectileSpawner.cs interpolated string `\"NULL\"` escape 영역 컴파일 에러·ternary 결과 변수 분리 fix. 본 PM 자성 #15 (Edit 후 컴파일 사전 검증 누락). EerieVillage `9879425` push 정합. **[2026-05-13 fileID 잘못된 측정 정정·자성 #16]** PD Inspector 측정 결과 영역 본 PM .asset 영역 fileID 영역 자식 GameObject 영역 매핑 영역. `grep -m 1` 영역 첫 GameObject 영역 = root 영역 영역 X. A08·A06·A12 .asset 영역 fileID 일괄 정정 (FX_PinkMagicArrow_Hit·FX_PinkArrow_Shoot·FX_Venom_Spray·FX_Icelight_Seal). 올바른 측정 = `awk m_Name + m_Father=0 정합`. EerieVillage `b26eb42`·`447ea92` push 정합. **[2026-05-13 CastFx 방향 + 진단 회수]** CastFx Instantiate 영역 facing+ProjectileAngleOffset+FxRotation 적용 (sprite 반대 방향 정정)·진단 Debug.Log 3종 revert. EerieVillage `7ad3319` push 정합. **[2026-05-13 A08 spawn 끝점·grace]** A08.asset OffsetDistance.x=1.5 (캐스팅 끝 spawn)·Projectile.OnTriggerEnter2D 영역 0.1초 grace 추가 (Hit FX Player 위치 회피). EerieVillage `eab215d` push 정합. **[2026-05-13 ScalingMode Hierarchy 전수]** 모든 fx spawn 영역 ParticleSystem.MainModule.scalingMode = Hierarchy 설정 (HitFxScale 정합 적용·7 파일 전수). EerieVillage `6ed6efe` push 정합. **[2026-05-14 자연 fade SelfDestruct]** Projectile.SelfDestruct 영역 즉시 Destroy 영역 → ParticleSystem Stop(emission)·Collider/박스 disable·_speed=0·0.5s 후 Destroy·FADE_START_RATIO 0.85. 발사 영역 영역 영역 trail 자연 연속. EerieVillage `2ee5084` push 정합. **[2026-05-14 A08 캐스팅 제거·적 조준]** A08.asset OffsetDistance.x=0·CastFx=null·TargetEnemyOnFire=1·ActiveSkillData.TargetEnemyOnFire 신규·ProjectileSpawner.Trigger 영역 nearest enemy 방향 발사. 벽·발판 관통 X 영역 = Projectile.Update Layer 0·16 OverlapPoint 영역 정합. EerieVillage `55ee4f3` push 정합. **[2026-05-14 HitFx sortingOrder·적 조준 하단]** 모든 hit fx (Projectile·LightningStrike·MeleeArea·Laser) Renderer.sortingOrder += 100 (Enemy 영역 위)·ProjectileSpawner TargetEnemyOnFire 영역 toEnemy.y -= 0.5 (hitbox 영역 영역 영역 적중). EerieVillage `eb33e64` push 정합. **[2026-05-14 적 조준 중간 보정]** toEnemy.y -= 0.5 → 0.25 (이전·1차 중간·너무 하단 정정). EerieVillage `b52c99d` push 정합. | **진행중** | 신규 `Assets/Scripts/MyUI/SkillInventoryHUD.cs` (OnGUI 좌상단·장착 액티브 DisplayName·Lv·CooldownRemaining/EffectiveCooldown·패시브 카운트). PlayerController.Awake 자동 부착. 보강: ProjectileSpawner fallback prefab에 SpriteRenderer + 동적 흰색 원 sprite + 속성별 색상 (Fire 주황·Frost 하늘·Dark 보라·Lightning 노랑·Physical 흰). Unity 기본 자원 활용 — Texture2D 동적 생성 16×16 알파 원. **[이펙트 개선 완료 2026-05-13]** (PD 지시 "이펙트 개선작업은 완료처리"). 본 세션 (`cranky-wescoff-e855b0`) 누적: (1) 5 스킬 통합 + 1~5 키 발사 시스템 — A02·A04·A05·A_Laser·A13 (EerieVillage `2ebf313`). (2) Inspector 즉시 반영 필드 확장 — HitboxSize·OffsetDistance(Vector2)·OffsetXY·FxRotation·HitFxScale·DamageFrameDelay·EnableRepeatDamage·MaxHitCount·RepeatFrameInterval. (3) hit 모션 + flash 연출 (붉은색·alpha 50%·1 frame) — Animator self-loop transition + Health.DecrementBypassInvulnWithHit. (4) Scene 잔존 박스·FX 6개 cleanup + HideFlags.DontSave 8 spawn 지점 (EerieVillage `60e28e3`) — Edit Mode execute_code 측정 시 Scene 오염 방지 표준 확립. (5) FxRotation 박스 미적용 분리 (EerieVillage `ea7d32f`) — 박스(판정) = facing 만 · 이펙트(시각) = facing + FxRotation. 4 case 검증 (facing R/L × FxRotation 0/90 박스 무반응·facing 좌/우 정확 반전). (6) A05 좌우 베기 이펙트 Player 동조 (EerieVillage `f6c6eb5`) — MeleeAreaSpawner.SetParent(true) 추가·Player 전진 시 이펙트 밀림 정정 (Δ+2.0 동조 측정). 양 레포 push 정합. | — | **이펙트 개선 영역 = 완료 처리.** HUD·Icon UI·Layer Lab 카드 정합 등 잔여 사항은 PD 후속 결정 대기. 인수인계서: `공유/조직공지/2026-05-13_BT12-Dev_세션종결인수인계.md`. **[이펙트 작업 완성 확정 2026-05-14]** (PD 발화 "스킬 이펙트 작업은 완성이야. 임의로 투사체 판정 범위나 크기 등이 바뀌지 않도록 지금 상태를 잘 기록해"). 본 PM SOT 신설: `프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md` — 13 활성 스킬 (A01·A02·A03·A04·A05·A06·A08·A11·A12·A13·A14·A15·A_Laser) 핵심 필드 표 + 박스↔이펙트 분리 원칙 + EerieVillage stamp `1a1de0c`. **변경 금지 원칙**: PD 직접 명시 지시 없이 임의 변경 금지. 변경 시 SOT §4 갱신 + commit + PD 보고 의무. 본 PM·차기 세션 PM 모두 본 SOT 준수. | | BT12-Dev-Death | 2026-05-09 | **스킬 습득 후 사망 버그 지시** — PD 직접 발화: "스킬 습득 후 일정시간이 지나면 왜 플레이어가 갑자기 죽는거지? 버그를 수정해줘." | **완료 2026-05-10 (PD 정합 확인)·아카이브 이동 영역** | (1) Projectile.OnTriggerEnter2D에 PlayerController 명시 차단 (defensive proxy·자기 hit 차단). (2) Health.Decrement·DecrementSilent·Die에 Debug.Log + System.Environment.StackTrace 추가 (사망 호출자 추적). **(3) 근본 fix 1 2026-05-09 EerieVillage `b37b4a6`**: HealthIsZero.Execute에 sender 검증 가드 추가 (PlayerController 보유 Health만 PlayerDeath 발화). **인수인계서 가설(EnemyController patrol → PlayerEnemyCollision) 부정** — Player Decrement 로그 부재. **근본 원인 1**: HealthIsZero.Execute가 health sender 검증 없이 무차별 Schedule() 발화. BT12-Dev Phase 2-B 투사체가 사상 처음 Enemy.Health.Decrement → Enemy의 HealthIsZero가 PlayerDeath 직결 노출. **PD 결정 (2026-05-09) "1 즉시 적용해"** — A안 1줄 fix 즉시 적용. pm-auditor Pass + Minor 1 (매니페스트 등록 정정 적용) + Improvement 2. **(4) 근본 fix 2 2026-05-09 EerieVillage `33eaa55`**: ProjectileSpawner fallback Scene GameObject 잔존 fix. **(10) 근본 fix 8 + 임시 fix 2026-05-10 EerieVillage `6a825fc`** (PD 지시 3건·MCP 자율 진단·검증 정합): PD 보고 — 투사체 영역 적이 죽지 않음·경험치 X·레벨업 X. PD 지시 — (1) 기본 공격력 5 고정 (임시) (2) 죽는 모션 + 소멸 (3) 경험치 + 레벨업. 본 PM MCP 자율 진단 — execute_code 영역 PlayerSkillInventory.AddSkillByCardId 영역 카드 추가 + Player·Enemy 위치 강제 + Tick 영역 자동 발사 영역 → Console 영역 `[Health@Enemy] Decrement(damage=4) hp 4→0` 출력 정합 (투사체 hit 정합) **그러나 [ExperienceSystem] X·[EnemyDeath] X** → **Projectile.cs 영역 Schedule 호출 누락** 확정. **근본 fix 2종**: (1) damage Mathf.Max(_runtime.CalculateEffectiveDamage(), 5) — 임시 5 하한 (PD 지시) (2) Enemy hp 0 도달 영역 Schedule().enemy = enemy 추가 — AttackHitbox.cs:70~76 패턴 정합. **MCP Play 검증**: damage=5·hp 4→0·ExperienceSystem.OnEnemyKilled·GainXP·LEVEL UP Lv.1→2→3→4·SkillSelectionUI Show·카드 확정 정합. **(9) 근본 fix 7 2026-05-10 EerieVillage `f501960`** (PD "MCP 활용해서 네가 직접 체크해" + 본 PM MCP 자율 진단·fix·검증·PD 자성 #13): 본 PM Inspector·Animator·Console MCP 직접 점검 영역. Enemy.controller `controller_get_info` 영역 — parameters: velocityX·velocityY·hurt·death·grounded · Idle/Run/Hurt → Death/Hurt **transition X** 영역 발견. Schedule 직접 호출 영역 검증 — `enabled=false`·`collider=false`·`simulated=false` 적용 영역 — **Animator state = Baddie-Idle/Run 영역 영역**. 추가 진단 — `Time.timeScale = 0` (LevelUp 카드 선택 모드) + Animator updateMode = Normal → Animator.Update 정지 → death Trigger 호출 영역 transition X. **근본 fix 2종**: (A) Enemy.controller transition 5 추가 (Idle→Death·Idle→Hurt·Run→Death·Run→Hurt·Hurt→Death·`manage_animation controller_add_transition` 직접) (B) EnemyDeath.cs `animator.updateMode = AnimatorUpdateMode.UnscaledTime` 추가 → timeScale 무관 영역 Animator 정합 영역. 검증 — anim.SetTrigger("death") + anim.Update(0.5f) → Baddie-Death 진입 정합. 진단 Debug.Log 회수 (Projectile 8·AttackHitbox 1·EnemyDeath 1). **(2026-05-10 세션 종결)** — 인수인계서 `공유/조직공지/2026-05-10_BT12-Dev_세션종결인수인계.md`. 양 레포 push 정합 — EerieVillage `1ef1989`. 본 세션 commit 누적 21건. 영역 영역: 사거리 차이 PD 검증·Hurt/Death animation·Wall Layer 영역. **(8) 진단 도구 fix 6 2026-05-10 EerieVillage `d6764ce`** (PD A+B 결정·feedback_pm_root_diagnosis_priority 2차 적용): PD Console 분석 결과 본 PM 가설 5회 누적 부정확 자성. 핵심 발견 — 투사체 hit X·**AttackHitbox(BT7-Dev VS 순수형 자동 근접)** 영역 hit (t=4.15·t=4.66 hp 4→1·1→0). t=5.35 [Projectile][Enter] other=Enemy → Enemy Collider 활성 → **EnemyDeath.Execute 호출 X 영역 확정**. AttackHitbox.cs:75 `Schedule` 호출 영역 Execute 영역 호출 영역 의문 → 진단 Debug.Log 2종 추가: [AttackHitbox][Schedule] (col·enemy·hp·t)·[EnemyDeath][Execute] (enemy·collider.enabled·t). pm-auditor 통과 + Minor 1 (회수 트리거 명시) + Improvement 1 (_collider 동시 캡처) 수용. 회수 의무: PD 사망 원인 확정 직후 본 PM revert commit. **(7) 진단 도구 fix 5 2026-05-09 EerieVillage `d27a63f`** (PD A안 결정·feedback_pm_root_diagnosis_priority 영역 적용): PD 4차 보고 "여전히 적에게 제대로 피격되지 않고 통과하고 있어" → 본 PM 가설 4회 누적 부정확·회귀 1회 → 가설 즉시 중단·실측 우선·진단 Debug.Log 영역 추가. Projectile.OnTriggerEnter2D 영역 8 분기 진입·return·Hit 시점 영역 [Projectile][...] prefix 통일 영역 → PD Play Console 영역 호출 여부·other 정보·Layer·EnemyController·Health 영역 정확 진단 → 근본 원인 확정 후 fix. 회수 의무 명시 (PD Console 수령 + 근본 fix 후 일괄 제거). pm-auditor 통과 (조건부) + 권고 4종 (prefix 통일·가설 X·회수 명시·PD 안내) 수용. **(6) 회귀 정정 fix 4 2026-05-09 EerieVillage `9eebbec`** (C3 자진 고지): fix 3 영역 Kinematic Rigidbody2D 추가가 회귀 유발 — PD 3차 보고 "여전히 적이 플레이어의 투사체에 피격되지 않아". **근본**: Enemy = KinematicObject 상속 영역 Kinematic Rigidbody2D → Projectile Kinematic 영역 추가 시 Kinematic vs Kinematic + useFullKinematicContacts=false (기본값) → OnTriggerEnter2D 발화 X 영역 회귀. **본 PM 자성 #11 (헌법급)**: C39 위반·KinematicObject.cs:76 영역 사전 Read X. **fix**: ProjectileSpawner.CreateFallbackProjectile 영역 Rigidbody2D 영역 5 라인 제거 → `33eaa55` 시점 Static vs Kinematic Trigger 발화 정합 복원 (DebuffStackLimit 정정 영역 그대로 유지). **헌법급 feedback `feedback_new_code_existing_system_dependency_unmeasured` 신설** (신규 코드 영역 기존 시스템 의존성 미실측 금지·재발 차단 3 단계 의무). **(5) 근본 fix 3 2026-05-09 EerieVillage `fe65592`**: PD 2차 재검증 결과 ("판정 X 또는 효과 X") → 본 PM 진단 — **결함 1**: A01·A02·A03·A14·A15 영역 DebuffStackLimit 무차별 3 적용 (본 PM Phase 2-C placeholder 무차별 채움) → StatusApplier 가드 통과 → 의도 외 DebuffStack 트리거. **결함 2**: ProjectileSpawner.CreateFallbackProjectile Rigidbody2D 부재 → Trigger 판정 안정성 부족. **PD 결정 "3 동시 진행해"** — 옵션 3 양 결함 동시 적용. 5 asset DebuffStackLimit 3→0 + Rigidbody2D Kinematic 추가 (gravityScale 0·CollisionDetectionMode2D.Continuous). pm-auditor Conditional Pass + **Major 1 (헌법급 feedback `feedback_scriptable_object_field_blanket_fill.md` 신설·C39-10 위반·근층 원인 명문화)** + Improvement 2. **PD 1차 재검증**: Player 사망 X 정합·**잔존 투사체 1개 영구 노출** (PD 첨부 이미지). **근본 원인 2**: `Resources/Skills/Projectiles/Default` prefab 부재 → `LoadProjectilePrefab` fallback이 `new GameObject`로 Scene 영역 GameObject 생성·반환 → `Object.Instantiate(prefab,...)`가 이를 prefab으로 사용 → 사본은 정상 SelfDestruct·**원본 Scene GameObject는 Initialize 미호출·영구 잔존**. **fix (옵션 J)**: LoadProjectilePrefab은 Resources prefab만 반환·부재 시 null. Trigger 영역 prefab null 시 `CreateFallbackProjectile` 직접 호출 (Instantiate X·자기 자신 발사체). pm-auditor Pass + Minor 1 (line 65 주석 정합 영역 후속) + Improvement 1. | — | **PM 후속**: PD 2차 Play 재검증 (적 처치 후 Player 정상 + 투사체 발사 후 정상 SelfDestruct + 잔존 투사체 0건) → 정상 시 BT12-Dev-Death 완료 아카이브 이동. Enemy 사망 처리 발화 경로 후속 검증 (이전 Improvement 2 영역). | | BT12-MVP-A | 2026-05-08 | **경험치·레벨업·스킬 카드 선택 UI** — PD 직접 지시 2건 (1) 적 처치 → EXP → 레벨업마다 스킬 카드 3개 선택 기능 (2) 레벨업 UI (스킬 효과 추후·UI만). PD 첨부 예시 영역 ("기술 선택" 화면 — 카드 3장 가로·색상 배너·원형 아이콘·동심원·"레벨 N"/"최대"·"확인" 버튼). PD 결정 (β) 채택 — BT12-Dev 보류 일부 해제·BT12-MVP-A 분리 항목 진행. **PD 결정 D안 (2026-05-09)** — 기능 우선·그래픽 디테일 차후 영역. | **D안 완료 2026-05-09** | [Phase 1 완료] `프로젝트/EerieVillage/개발/spec/BT12-MVP-A_설계_v1.md` (~600 라인). [Phase 2-A 완료] EerieVillage `047661c` — 시스템 코드 6 + JSON 테이블. [Phase 2-B 코드 완료] EerieVillage `5b2b753` — UI 컴포넌트 2 + LevelUpManager 통합. **[Phase 2-B asset 5 완료 2026-05-08]** EerieVillage `755a51c` — `Assets/Data/SkillPlaceholders/{A01_jineonbu, A05_hagikjin, P01_bonghwanggyeok, P12_saengmyeongkkot, AW01_cheonbugyeongmun}.asset` (5) + 각 .meta (5) + folder meta 2 = 12 파일. C49 표준 — Phase 1 dev-team-lead Opus 첫 정합 호출 + Phase 2 Sonnet 위임 + Phase 3 PM 검증. **dev-team-lead 자진 고지** — 설계서 v1 §2-4 영역 P01·P12·AW01 BT11-Plan v0.2 정합 X (3건 정정 적용). **설계서 v1 §2-4 + §7-1 정정 완료** (commit 후속). PD Editor 가이드 신규 `BT12-MVP-A_Phase2B_PDEditor가이드.md`. 대화로그 엔트리 10. | — | **PM 후속 대기**: ① Phase 2-B B (Prefab) + C (Scene 통합) — **PD 직접 발화 (2026-05-08): "단계1은 완료. 단계2, 3은 개발팀에서 작업해줘" + "E"** → 옵션 E 채택 (Claude Desktop Unity MCP 위임) → 본 PM 의뢰서 작성 `BT12-MVP-A_Phase2B_ClaudeDesktop의뢰서.md` (~16K) → PD Claude Desktop 새 세션 영역 의뢰서 첨부 영역 작업 진행 → EerieVillage commit·push → 본 worktree PM 보고 ② Phase 3 dev-team-lead 통합 검증 (Phase 1 + 2-A + 2-B asset + Prefab + Scene + BT5-Dev/BT7-Dev 회귀) ③ **단계 4 PD Play 검증** (적 처치 → EXP → 레벨업 → UI 노출 → 카드 선택 → 게임 재개) ④ 기획팀 별도 안건 — `01_카드_풀.md` line 114 P12 = "도약강화" 잔존 정정 (`02_스킬_효과_컨셉.md` line 381·418 영역 동기화 X) ⑤ icon sprite asset 5장 별도 작업 ⑥ 완료 아카이브 이동. (PD Editor 가이드 영역 = 옵션 D 보류 영역·차기 영역 활용 가능) | diff --git a/공유/대화로그/EerieVillage/2026-05-15.md b/공유/대화로그/EerieVillage/2026-05-15.md new file mode 100644 index 0000000..d8c5121 --- /dev/null +++ b/공유/대화로그/EerieVillage/2026-05-15.md @@ -0,0 +1,129 @@ +# EerieVillage 대화로그 — 2026-05-15 + +## [BT12-Dev-Clone 1단계 완료] 개발팀장 Opus 직접 설계 (A10 분신 스킬) + +**시간**: 2026-05-15 16:56 +**주체**: 개발팀장 (`dev-team-lead`) +**Task ID**: PM 매니페스트 `BT12_Dev_Clone_A10_2026-05-15_2200` (4 target_files) +**C49 표준 프로세스 시범**: 1단계 (개발팀장 Opus 설계) → 2단계 (클라이언트팀 Sonnet 구현) → 3단계 (개발팀장 Opus 검증) + +### 결정·근거·영향 (C32 의무 3요소) + +**결정**: A10 분신 스킬 구조 = (나) `CloneInstance` 단일 MonoBehaviour + Player Inventory hook + 0.5초 지연 큐 + `IsCloneFireActive` 분기. + +**근거**: +1. PD 명세 5항목 (위치 facing 반대 1유닛·반투명 alpha 0.5·동일 스킬·50% 반감·0.5초 딜레이) 전수 충족 +2. v0.4 CSV A10 행 "분신 1기·동일 패턴 모방·공격력 비율 감소·무적" 정합 +3. C11 자원 효율 — MonoBehaviour 1기·Singleton (별도 Inventory mirror 부재) +4. C11 코드 직관성 — "Player Fire 0.5초 뒤 분신 위치에서 동일 Effector + 50% damage" 단 1줄 멘탈 모델 +5. 옵션 (가) 별도 GameObject + Inventory mirror = 코드 중복 (장착·Lv·각성 2중 동기화 부담) → 기각 +6. 옵션 (다) Player+Clone 2회 동시 발동 = PD 명세 5번 "0.5초 뒤" 직접 위반 → 기각 + +**영향**: +- 기존 시스템 영향 최소 — `PlayerSkillInventory`에 4필드 + 1이벤트 추가, `ActiveSkillRuntime.Fire()` 1줄, `CalculateEffectiveDamage()` 1줄, `SkillFireEvent.Execute` Minion case CardId 분기, `SkillRuntimeFactory.AvailableCardIds` "A10" 추가 +- 6개 Effector (Projectile·MeleeArea·LightningStrike·Laser·PoisonSwamp·SpiritFire) 영역 `IsCloneFireActive` 분기 일관 추가 (spawn 위치·facing) — 약 18줄 +- BT12-Dev-Vis 진행 13 스킬 정상 동작 보장 (분신 hook이 Player 발동 영향 X — `IsCloneFireActive == false` 조건) +- Lv 업·각성 영향 X (분신 자체 Lv 업 X — Player Lv 업 시 분신 발동 damage 자동 갱신) + +### 기각안 5건 (C32 의무 — 결정 엔트리 기각안 필드) + +1. **별도 GameObject + 자체 `PlayerSkillInventory` mirror** — 코드 중복·동기화 부담 +2. **Effector 한 번 호출 시 Player+Clone 2회 발동 (분신 = sprite만)** — PD 명세 0.5초 딜레이 위반 +3. **`PlayerSkillInventory.transform.position` swap (1 frame)** — Camera·HUD·다른 컴포넌트 transform 참조 부작용 위험 +4. **분신 lifetime 8초 (A11 동등)** — v0.4 CSV "분신 1기" + "긴 주기" 의미 무너짐 +5. **분신 facing이 Player와 독립 (적 방향 자체 추적)** — "동일 패턴 모방" v0.4 CSV 정합 X·분신 = 독립 actor 의미 회귀 + +### 산출물 + +- `프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md` §A10 신설 (16 sub-section) +- `프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md` §3 A10 추가 + §4 변경 이력 갱신 +- `공유/PD_지시_트래킹/개발팀_PD_지시_로그.md` BT12-Dev-Clone 행 1단계 완료 표기 + +### PD 결정 안건 (3단계 검증 시 보고) + +1. **BaseCooldown 30** PM 추정 — balance-designer 후속 확정 영역 +2. **facing 변경 시 분신 위치 처리** — spawn 시점 고정 vs Player 추종 (PM 1차: Player 자식 부착 + spawn facing 고정) +3. **분신 무적 spec** — collider 미부착 / 적이 분신 위 올라타거나 적 투사체 통과 영역 Play 검증 +4. **Lv 업 (분신 수 증가 등) 1차 미반영** — 후속 PD 결정 안건 + +### 2단계 작업 단위 분해 (Sonnet Task 위임 예정) + +**파일 13종**: + +| # | 파일 | 작업 | +|---|------|------| +| 1 | `Assets/Scripts/Skills/Effectors/CloneInstance.cs` | 신규 — MonoBehaviour + 0.5초 지연 큐 | +| 2 | `Assets/Scripts/Skills/Effectors/CloneEffector.cs` | 신규 — IEffector 구현 | +| 3 | `Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs` | 수정 — 4필드 + OnPlayerSkillFired 이벤트 | +| 4 | `Assets/Scripts/Skills/Runtime/ActiveSkillRuntime.cs` | 수정 — Fire() + CalculateEffectiveDamage() | +| 5 | `Assets/Scripts/Skills/Events/SkillFireEvent.cs` | 수정 — Minion CardId 분기 + Cleanup reset | +| 6 | `Assets/Scripts/Skills/Runtime/SkillRuntimeFactory.cs` | 수정 — AvailableCardIds "A10" 추가 | +| 7~12 | 6개 Effector | 수정 — IsCloneFireActive 분기 일관 추가 | +| 13 | `Assets/Resources/Skills/Active/A10_bunsin.asset` | 신규 — A11 동등 패턴 + A10 고유 필드 | +| 14 | `Assets/Tests/Editor/CloneSkillTests.cs` | 신규 — EditMode 7건 | + +--- + +## [BT12-Dev-Clone PD 결정 4건 반영 2026-05-15] + +**시각**: 2026-05-15 (1단계 결과 보고 후 PD 응답) +**주체**: PM 직접 SOT 갱신 (C48 시범 — Task 회피) +**영역**: BT12-Dev-Clone 1단계 설계 핵심 영역 변경 +**유형**: PD 결정 채택 + SOT 4종 갱신 + +### PD 결정 4건 + +| # | PD 명세 | PM 1차 안 | PD 결정 | +|---|---------|----------|---------| +| 1 | BaseCooldown | 30초 | **25초** | +| 2 | lifetime | 영구 1기 (재발동 시 대체) | **12초 자동 소멸 + Singleton 1기** | +| 3 | facing | 고정 (PM 1차) | **고정 확정** | +| 4 | 무적 | Collider 미부착 (PM 1차) | **Collider 미부착 확정** | +| 5 | Lv 업 | 분신 수 X · 1차 미반영 | **분신 수 X · 추후 지속시간↑ + 플레이어 참조 데미지 비율(%)↑** (balance-designer 후속) | + +### 핵심 변경 — lifetime 12초 자동 소멸 + +PM 1차 영구 1기 (Singleton·재발동 시 대체) → PD 결정 **12초 지속 + Singleton 1기**. spawn 시점 `unscaledTime + 12초` 후 자동 destroy. 12초 내 재발동 시 기존 destroy + 새 spawn (Singleton 패턴). BaseCooldown 25초 < lifetime 12초 → 분신 활성 중 재발동 시 자동 갱신. + +### SOT 반영 완료 (PM 직접 Edit) + +| 파일 | 영역 | 변경 | +|------|------|------| +| `프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md` | §A10-1 | lifetime 12초·BaseCooldown 25·Lv 업 메커니즘 명시 | +| `프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md` | §3 A10 | BaseCooldown 25·MinionLifetime 12·PD 결정 4건 주석 | +| `프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md` | §4 변경 이력 | PD 결정 4건 행 추가 | +| `공유/PD_지시_트래킹/개발팀_PD_지시_로그.md` | BT12-Dev-Clone 사후 조치 | PD 결정 4건 표기 | +| `공유/대화로그/EerieVillage/2026-05-15.md` | 본 엔트리 | PD 결정 엔트리 | + +### 2단계 진행 결정 + +PM 권고 (b) 4분할 채택 (PD 명시 옵션 결정 X·PM 권고 default 적용). α 분할 진행 대기: +- **α**: `CloneInstance.cs`·`CloneEffector.cs` 신규 2 파일 (코어 컴포넌트) +- **β**: `PlayerSkillInventory`·`ActiveSkillRuntime`·`SkillFireEvent`·`SkillRuntimeFactory` 수정 4 +- **γ**: 6 Effector `IsCloneFireActive` 분기 일관 추가 +- **δ**: `A10_bunsin.asset` 신규 (BaseCooldown 25·MinionLifetime 12·PD 결정 반영) + `CloneSkillTests.cs` EditMode 7건 + +### 잔존 정리 영역 (commit 직전 일괄) + +설계 v1 §A10 1421·1429·1522·1523·1570 라인 영역 BaseCooldown 30 잔존 표기 → 25 정정. 본 응답 핵심 SOT (§A10-1·§3 A10) 우선 반영·세부 표 영역 후속 일괄 정정 (commit 직전). + +### 결정·근거·영향 + +**결정**: PD 결정 4건 즉시 SOT 반영. 2단계 (b) 4분할 진행 채택. + +**근거**: PD 2026-05-15 직접 결정 (= C1). + +**영향**: +- lifetime 12초 변경 = 1단계 설계 핵심 영역 변경. CloneInstance Update에 lifetime 타이머 추가 의무 (α 단계 구현 영역) +- Lv 업 메커니즘 명시 = balance-designer 후속 수치 안건 명확화 (지속시간 Lv별 증가량·데미지 비율 Lv별 증가량) +- BaseCooldown 25 < lifetime 12 → 분신 활성 중 재발동 시 갱신 가능 (25초 마다 분신 재spawn) + +### 관련 규칙 + +- C1 (PD 결정 = 승인) · C5 · C22 (PD 도입 용어 보존 — "지속시간"·"분신 수"·"플레이어 참조 데미지 비율(%)") · C25 · C32 · C34-11 +- C43 호칭 라우팅 (개발팀 직접 수령) +- **C48 시범** (PM 직접 SOT Edit·Task 회피) +- **C49 1단계 완료** (개발팀장 설계)·2단계 Sonnet/PM 진행 대기 +- **C50** (1단계 25K + 2단계 60~80K 4분할 + 3단계 15~20K = 본 BT12-Dev-Clone 총량 100~125K) + +--- diff --git a/프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md b/프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md index 7577911..add5dbf 100644 --- a/프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md +++ b/프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md @@ -1034,6 +1034,7 @@ Phase 2는 **PM이 별도 Task로 클라이언트팀 Sonnet에 위임**하는 | 일시 | 변경 | 사유 | 기안 | |------|------|------|------| | 2026-04-24 | v1.0 Phase 1 설계 — 아키텍처 4계층·인터페이스 4+4종·데이터 흐름·자동 발동 사이클·각성 조건 매니저·카테고리 매핑 6+5+4·BT7-Dev 통합 영역 | BT12-Dev PD 직접 지시 "스킬 시스템 설계 진행" + C49 1단계 시범 적용 | 개발팀장 | +| 2026-05-15 | §A10 분신 스킬 상세 설계 신설 — PD 명세 5항목 (위치·반투명·동일 스킬·50% 반감·0.5초 딜레이) + 구조 결정 (CloneInstance 단일 + 0.5초 지연 큐) + 신규/수정 파일 13종 분해 + 기각안 5건 + EditMode 7건 + 3단계 검증 항목 7종 | BT12-Dev-Clone PD 직접 지시 + C49 1단계 시범 (개발팀장 Opus 설계 → 클라이언트팀 Sonnet 구현 → 개발팀장 검증) | 개발팀장 | --- @@ -1059,6 +1060,519 @@ Phase 2는 **PM이 별도 Task로 클라이언트팀 Sonnet에 위임**하는 --- +## §A10. 분신 스킬 상세 설계 (BT12-Dev-Clone 2026-05-15) + +> **PD 직접 지시 (2026-05-15)** 원문: +> > "1. 이번에는 분신 스킬을 구현해줘. +> > 2. 이 스킬을 사용하면 플레이어의 x좌표 1 뒤쪽에 반투명한 형태의 플레이어의 분신이 생성되어서 플레이와 동일한 스킬을 사용해야 해. (단, 분신의 공격은 플레이어의 공격력의 50% 반감되어야하고, 플레이어보다 0.5초 뒤 사용해야 해. (공격 시작 딜레이))" +> +> **C49 표준 프로세스 시범 — 1단계 (개발팀장 Opus 설계)**. + +### A10-1. PD 명세 5항목 확정 + +| # | 항목 | PD 명세 (원문 인용) | +|---|------|---------| +| 1 | 위치 | "**플레이어의 x좌표 1 뒤쪽**" — facing 반대 방향 1유닛 (예: facing=오른쪽 → 분신 x = player.x - 1) | +| 2 | 외형 | "**반투명한 형태의 플레이어의 분신**" — Player sprite 복제 + alpha 0.5 (개발팀장 재량) | +| 3 | 동작 | "**플레이와 동일한 스킬을 사용**" — Player 장착 액티브 발동 시 분신도 동일 카드 발동 | +| 4 | 공격력 | "**분신의 공격은 플레이어의 공격력의 50% 반감**" — damage * 0.5 | +| 5 | 타이밍 | "**플레이어보다 0.5초 뒤 사용** (공격 시작 딜레이)" — Player Fire 시점 + 0.5초 지연 큐 | + +**기획 SOT v0.4 CSV A10 행 정합** (인용): +> `A10,액티브,분신,D. 소환,긴 주기로 분신 1기를 생성한다. 플레이어 공격 패턴을 동일하게 모방해 자동 공격 (분신은 무적이나 공격력은 플레이어보다 비율 감소),추가 공격 기회` + +PD 본 발화에 없는 v0.4 CSV 명세 합리적 기본값 (PM 1차 안 채택): +- **분신 lifetime**: **12초 자동 소멸 + Singleton 1기 유지** (PD 2026-05-15 직접 결정) — spawn 시점 unscaledTime + 12초 후 자동 destroy. 12초 내 재발동 시 기존 분신 destroy + 새 분신 spawn (Singleton 패턴·BaseCooldown 25초 정합) +- **BaseCooldown**: **25초** (PD 2026-05-15 직접 결정 — PM 1차 30초 → PD 조정 25초) +- **분신 무적**: 유지 — v0.4 명시 + PD 2026-05-15 직접 결정 "무적으로 진행 (Collider 미부착)". 적 투사체·벽·player·enemy 모두 통과 +- **collision**: wall·player·enemy 모두 무충돌 (반투명·무적 정합) — 시각 GameObject 전용 +- **Lv 업 메커니즘** (PD 2026-05-15 직접 결정): **분신 수 증가 X** (1기 고정). 추후 **지속시간 ↑ + 플레이어 참조 데미지 비율(%) ↑** (PassiveSkill Lv 업 시 분신 lifetime·damage multiplier 증가 명세 — balance-designer 후속 수치 확정) + +### A10-2. 구조 결정 — 3개 옵션 검토 + +| 옵션 | 설명 | 장단점 | +|------|------|-------| +| (가) | `CloneController` 별도 GameObject + 자체 `PlayerSkillInventory` mirror | (장) 분신 = 독립 actor·테스트 격리 (단) 코드 중복 — 인벤토리·Lv·각성·이벤트 구독 2중 동기화 부담 | +| **(나) ✅** | **`CloneInstance` 단일 MonoBehaviour + Player Inventory hook** — Player Fire 시 0.5초 지연 큐 enqueue → 분신 위치 anchor로 동일 Effector 재호출 + damage 50% 반감 | (장) Effector 코드 재활용·인벤토리 단일 SOT 유지·동기화 부담 0 (단) Effector가 inventory 컨텍스트 분기 필요 — `PlayerStats` 50% 반감 처리 | +| (다) | Effector 한 번 호출 시 Player+Clone 2회 발동 (분신 = sprite만) | (장) 최소 구현 (단) "0.5초 뒤" PD 명세 위반 — 즉시 2회 발동은 spec 어긋남 | + +**채택 = (나)**. 근거: +1. **PD 명세 5번 (0.5초 딜레이) 충족**: (다) 즉시 발동은 spec 위반 +2. **PD 명세 3번 (동일 스킬)**: Effector 재활용으로 13종 카드 무차별 지원 +3. **C11 자원 효율**: 별도 Inventory mirror 부재 — 메모리·GC 부담 최소 +4. **C11 코드 직관성**: 분신 = "Player Fire 0.5초 뒤 분신 위치에서 동일 Effector 호출 + 50% damage" 단 1줄 멘탈 모델 + +### A10-3. 신규 컴포넌트 — `CloneInstance` MonoBehaviour + +**파일**: `Assets/Scripts/Skills/Effectors/CloneInstance.cs` (신규) + +**계약**: + +```csharp +namespace EerieVillage.Skills.Effectors +{ + /// + /// A10 분신 인스턴스. Player 자식 부착 X (독립 GameObject — Player 이동 시 위치 미동조·고정 위치 1기). + /// PD 명세 (2026-05-15): + /// - Player x좌표 1 뒤쪽 spawn (facing 반대 방향 1유닛) + /// - 반투명 sprite (alpha 0.5) + /// - Player 발동 시 0.5초 뒤 동일 Effector 발동 + /// - damage 50% 반감 + /// - 무적·무충돌 (collider 미부착) + /// + public class CloneInstance : MonoBehaviour + { + // 정적 Singleton — 분신 1기 유지 (재발동 시 기존 destroy) + private static CloneInstance _current; + + private PlayerSkillInventory _playerInventory; + private float _spawnFacingX; // spawn 시점 Player facing.x (분신 facing 고정) + + // 지연 큐: (발동 시각, Runtime, Inventory 컨텍스트) + private readonly Queue _pendingQueue = new Queue(); + + private struct PendingFire + { + public float TriggerTime; // unscaledTime + 0.5초 + public ActiveSkillRuntime Runtime; + } + + public static void SpawnOrReplace(PlayerSkillInventory playerInventory, ActiveSkillData cloneData) { /* §A10-4 */ } + + public void EnqueuePlayerFire(ActiveSkillRuntime runtime) { /* §A10-5 */ } + + void Update() { /* §A10-5 — 큐 dequeue + Effector 재호출 */ } + + void OnDestroy() { /* Player Inventory unsubscribe + _current 정리 */ } + } +} +``` + +### A10-4. 분신 spawn 로직 (CloneEffector) + +**파일**: `Assets/Scripts/Skills/Effectors/CloneEffector.cs` (신규) + +```csharp +namespace EerieVillage.Skills.Effectors +{ + /// + /// A10 분신 Effector — Category D (Minion) 카테고리에서 CardId == "A10" 분기. + /// SkillFireEvent.Execute 영역 Minion case 분기: + /// if (data.CardId == "A10") effector = new CloneEffector(); + /// else effector = new SpiritFireSpawner(); (기존 A11) + /// + public class CloneEffector : IEffector + { + public void Trigger(ActiveSkillRuntime runtime, PlayerSkillInventory inventory) + { + // 분신 spawn 또는 교체 (Singleton) + CloneInstance.SpawnOrReplace(inventory, runtime.ActiveData); + // 분신 자체는 "발동"이 아닌 "생성" — 발동은 Player Fire 시 분신 인스턴스가 hook + } + } +} +``` + +**`CloneInstance.SpawnOrReplace` 동작**: + +```csharp +public static void SpawnOrReplace(PlayerSkillInventory playerInventory, ActiveSkillData cloneData) +{ + // 1. 기존 분신 destroy (1기 유지) + if (_current != null) { Destroy(_current.gameObject); _current = null; } + + // 2. Player 위치·facing 취득 + var pc = playerInventory.GetComponent(); + Vector2 facing = pc != null ? pc.Facing : Vector2.right; + float signX = facing.x < 0f ? -1f : 1f; + Vector2 playerPos = playerInventory.transform.position; + + // 3. PD 명세 — facing 반대 1유닛 (예: facing=오른쪽 → -1유닛) + Vector2 spawnPos = playerPos + new Vector2(-signX * 1f, 0f); + + // 4. Player sprite clone — SpriteRenderer 복제 + alpha 0.5 + var go = new GameObject("Clone_A10"); + go.hideFlags = HideFlags.DontSave; + go.transform.position = spawnPos; + + var playerSr = playerInventory.GetComponentInChildren(); + if (playerSr != null) + { + var sr = go.AddComponent(); + sr.sprite = playerSr.sprite; + sr.flipX = playerSr.flipX; // Player와 동일 방향 시각 (PD 명세 "분신" 외형) + sr.sortingOrder = playerSr.sortingOrder - 1; // Player 뒤쪽 + Color c = playerSr.color; + c.a = 0.5f; // 반투명 + sr.color = c; + } + + // 5. CloneInstance 컴포넌트 부착 + Player Inventory hook 구독 + var instance = go.AddComponent(); + instance._playerInventory = playerInventory; + instance._spawnFacingX = signX; + _current = instance; + + // 6. Player Fire 이벤트 구독 — 새 hook 신설 필요 (§A10-6) + playerInventory.OnPlayerSkillFired += instance.EnqueuePlayerFire; +} +``` + +### A10-5. Player Fire hook + 0.5초 지연 큐 + +**PlayerSkillInventory 신규 이벤트 (`§A10-6` 확장)**: + +```csharp +// PlayerSkillInventory.cs 신설 영역 +public event System.Action OnPlayerSkillFired; + +// ActiveSkillRuntime.Fire() 영역에 hook 추가: +// - Fire() 호출 시 Simulation.Schedule 발동 직후 +// - inventory.OnPlayerSkillFired?.Invoke(this) 호출 +// 이렇게 함으로써 분신이 자체적으로 Player Fire 시점을 감지 → 0.5초 지연 큐 enqueue +``` + +**CloneInstance Update + enqueue 로직**: + +```csharp +public void EnqueuePlayerFire(ActiveSkillRuntime runtime) +{ + // A10 분신 자체 발동 = 무한 재귀 방지 (분신은 분신을 발동하지 않음) + if (runtime.ActiveData.CardId == "A10") return; + + _pendingQueue.Enqueue(new PendingFire { + TriggerTime = Time.unscaledTime + 0.5f, // PD 명세 0.5초 딜레이 + Runtime = runtime + }); +} + +void Update() +{ + while (_pendingQueue.Count > 0 && _pendingQueue.Peek().TriggerTime <= Time.unscaledTime) + { + var pending = _pendingQueue.Dequeue(); + FireAtClonePosition(pending.Runtime); + } +} + +private void FireAtClonePosition(ActiveSkillRuntime runtime) +{ + var data = runtime.ActiveData; + if (data == null) return; + + // 분신 위치 anchor로 Effector 재호출 + // 핵심 패턴: PlayerStats.CloneDamageMultiplier (또는 _isCloneFire 플래그) 분기로 damage 50% 반감 + // 옵션 A — _playerInventory.Stats 임시 백업·multiplier 0.5 적용·Effector 호출·복구 + // 옵션 B — CloneInventoryWrapper 별도 객체 (Stats 사본·DamageMultiplier *= 0.5) — 채택 + + var cloneCtx = CloneFireContext.Create(_playerInventory, transform.position, _spawnFacingX); + IEffector effector = ResolveEffector(data); + if (effector != null) effector.Trigger(runtime, cloneCtx.WrappedInventory); +} +``` + +**`CloneFireContext`** (신규 헬퍼 — 별도 inventory 어댑터): + +```csharp +internal static class CloneFireContext +{ + // PlayerSkillInventory 직접 수정 없이 분신 발동 컨텍스트 분리 + // 옵션 1 — PlayerSkillInventory.IsCloneFireContext 플래그 (간단) + // 옵션 2 — 별도 wrapper (코드 직관성 ↑) + // 채택 = 1 — Effector 변경 최소 (PlayerSkillInventory 1 필드 추가만) +} +``` + +**최종 채택 = 옵션 1** (PlayerSkillInventory 플래그): + +```csharp +// PlayerSkillInventory.cs 신설 필드 +internal bool IsCloneFireActive = false; +internal Vector2 CloneFireOrigin = Vector2.zero; +internal float CloneFireFacingX = 1f; +internal const float CLONE_DAMAGE_MULTIPLIER = 0.5f; +``` + +각 Effector에서 `inventory.IsCloneFireActive` 분기: +- spawn 위치 = `inventory.CloneFireOrigin` (분신 위치) 사용 +- facing = `Vector2(inventory.CloneFireFacingX, 0)` 사용 +- damage = 기존 계산 결과 * `CLONE_DAMAGE_MULTIPLIER` (0.5) + +`ActiveSkillRuntime.CalculateEffectiveDamage()` 영역에 단 1줄 추가: + +```csharp +public int CalculateEffectiveDamage() +{ + // ... 기존 ... + float effective = ActiveData.BaseDamage * stats.DamageMultiplier * StackLevelFactor(StackLevel) * attrMult; + if (_inventory != null && _inventory.IsCloneFireActive) effective *= PlayerSkillInventory.CLONE_DAMAGE_MULTIPLIER; + return Mathf.RoundToInt(effective); +} +``` + +위치·facing 분기는 Effector 진입점 (ProjectileSpawner·MeleeAreaSpawner·LightningStrikeSpawner·LaserSpawner·PoisonSwampSpawner·SpiritFireSpawner) 영역 `inventory.transform.position` 대신: + +```csharp +Vector2 anchorPos = inventory.IsCloneFireActive ? inventory.CloneFireOrigin : (Vector2)inventory.transform.position; +Vector2 facing = ...; if (inventory.IsCloneFireActive) facing = new Vector2(inventory.CloneFireFacingX, 0); +``` + +`CloneInstance.FireAtClonePosition`: + +```csharp +private void FireAtClonePosition(ActiveSkillRuntime runtime) +{ + var inv = _playerInventory; + inv.IsCloneFireActive = true; + inv.CloneFireOrigin = transform.position; + inv.CloneFireFacingX = _spawnFacingX; + try + { + // SkillFireEvent.Execute 영역 그대로 재호출 + var ev = Simulation.Schedule(); + ev.Runtime = runtime; + ev.Inventory = inv; + } + finally + { + // Schedule 즉시 처리 X — 1 frame 후 reset (또는 SkillFireEvent.Execute 마지막에 reset) + // 채택: SkillFireEvent.Cleanup 영역 IsCloneFireActive=false 일관 reset + } +} +``` + +**reset 시점 결정 안건** (3단계 검증 영역): +- (가) SkillFireEvent.Cleanup 영역 reset — Simulation 일관 시점·자동 +- (나) 다음 frame Coroutine — race 회피 (다른 Player Fire 영역 영향 차단) +- 채택 = (가) — Simulation.Event Cleanup 영역 일관 reset + +### A10-6. ActiveSkillRuntime.Fire() 영역 OnPlayerSkillFired 발화 + +기존 코드: +```csharp +public void Fire() +{ + if (ActiveData.Category == ActiveCategory.SpecialJudge) { /* 확률 판정 */ } + var ev = Simulation.Schedule(); + ev.Runtime = this; + ev.Inventory = _inventory; +} +``` + +확장 1줄 추가: +```csharp +public void Fire() +{ + if (ActiveData.Category == ActiveCategory.SpecialJudge) { /* 확률 판정 */ } + var ev = Simulation.Schedule(); + ev.Runtime = this; + ev.Inventory = _inventory; + + // BT12-Dev-Clone 2026-05-15 — A10 분신 hook + if (_inventory != null && !_inventory.IsCloneFireActive) + _inventory.OnPlayerSkillFired?.Invoke(this); +} +``` + +**`IsCloneFireActive` 분기**가 중요 — 분신 발동도 OnPlayerSkillFired 호출 시 무한 재귀. Clone 컨텍스트에서는 발화하지 않음. + +### A10-7. SkillFireEvent.Execute 영역 Minion case + CardId 분기 + +기존: +```csharp +case ActiveCategory.Minion: + effector = new SpiritFireSpawner(); + break; +``` + +수정: +```csharp +case ActiveCategory.Minion: + if (data.CardId == "A10") effector = new CloneEffector(); + else effector = new SpiritFireSpawner(); + break; +``` + +**Cleanup 영역 추가** (분신 발동 reset): +```csharp +internal override void Cleanup() +{ + if (Inventory != null) Inventory.IsCloneFireActive = false; + Runtime = null; + Inventory = null; +} +``` + +### A10-8. A10 ActiveSkillData `.asset` 핵심 필드 + +**파일**: `Assets/Resources/Skills/Active/A10_bunsin.asset` (신규) + +A11_jeongnyeongbul.asset 동등 패턴 + A10 고유 필드: + +| 필드 | 값 | 근거 | +|------|---|------| +| CardId | "A10" | v0.4 CSV | +| DisplayName | "분신" | v0.4 CSV | +| EnglishName | "Clone" | 일관성 | +| Description | "긴 주기로 분신 1기를 생성한다. 플레이어 공격 패턴을 동일하게 모방해 자동 공격..." | v0.4 CSV 인용 | +| AttributeTags | 0 (None) | 분신 자체 속성 X — Effector 발동 시 카드별 속성 | +| TypeTags | 0 (None) | 동일 | +| maxLevel | 5 | 표준 | +| Category | 3 (Minion) | v0.4 CSV "D. 소환" | +| Trigger | 0 (OnTime) | 표준 | +| BaseCooldown | **25** | **PD 결정 2026-05-15** (PM 1차 30 → PD 조정 25). balance-designer 후속 Lv별 증가량 확정 | +| BaseDamage | 0 | 분신 자체 damage X — Effector 재호출 시 Player damage * 0.5 | +| HitboxSize | (0,0) | 분신 자체 판정 X | +| OffsetDistance | (0,0) | 분신 자체 spawn offset = facing 반대 1유닛 (코드 하드코딩 — PD 명세 정합) | +| MinionLifetime | **12** | **PD 결정 2026-05-15** — 12초 자동 소멸 + Singleton 1기 (BaseCooldown 25 < lifetime 12 영역 활성 중 재발동 시 25초마다 갱신). Lv 업 시 추후 증가 (balance-designer 후속) | +| OnHitFxPrefab | null | 분신 sprite는 코드 spawn (Player sprite 복제) | +| 기타 | 기본값 | - | + +**PD 결정 완료 (2026-05-15)**: BaseCooldown 25·MinionLifetime 12·facing 고정·무적 Collider 미부착·Lv 업 시 분신 수 X (지속시간+데미지 비율(%)↑·balance-designer 후속 수치). + +### A10-9. SkillRuntimeFactory.AvailableCardIds 추가 + +```csharp +static readonly HashSet AvailableCardIds = new HashSet +{ + "A02", "A13", "A04", "A05", "A_Laser", + "A08", "A12", + "A06", "A11", + "A10" // BT12-Dev-Clone 2026-05-15 신규 +}; +``` + +### A10-10. 무적·무충돌 처리 + +PD 명세 "분신은 무적" + 본 PM 합리적 기본값 "wall·player·enemy 모두 무충돌": + +| 요소 | 처리 | +|------|------| +| Collider2D | **미부착** — 무충돌 자동 (Trigger·Wall·Enemy 판정 모두 비활성) | +| Rigidbody2D | **미부착** — 물리 영향 X (중력·관성 모두 무관) | +| Health 컴포넌트 | **미부착** — 적 투사체 Decrement 호출 X — Health 검색 대상 외 | +| SpriteRenderer | **부착** — 시각 전용 (sortingOrder Player 뒤쪽) | + +**PD 검증 권고**: Play 시 분신 위에 적이 올라타거나 적 투사체 통과 — 무영향 검증. + +### A10-11. 분신 위치 동작 — 고정 vs Player 동조 + +**옵션 A — 고정 위치** (Player 이동 시 분신 그대로): +- spawn 시점 Player 위치 - 1유닛 = 분신 고정 위치 +- Player가 이동해도 분신은 그 자리 유지 → 분신 발동도 분신 위치에서 발동 +- VS류 게임 분신 표준 동작 (Vampire Survivors Pummarola 등) + +**옵션 B — Player 동조** (Player 자식 부착): +- 분신이 항상 Player x-1 위치 추종 +- "분신" 의미와 정합도 ↑ ("분신"은 분신·복제·따라다님) + +**채택 = B (Player 자식 부착)** — 근거: +1. PD 명세 "**플레이어의 x좌표 1 뒤쪽**" — 현재형 표현 = Player 이동 시 분신도 동조 자연 +2. v0.4 CSV "**플레이어 공격 패턴을 동일하게 모방**" — 분신이 Player 따라다니며 모방 = 자연 +3. 분신 1기 + Player 영구 동조 = 시각적 일관성 + +**구현**: `go.transform.SetParent(playerInventory.transform, true);` + spawn 시 `localPosition = (-signX * 1f, 0, 0)` + +**facing 변경 시**: Player facing 변경 시 분신의 "x 1 뒤쪽" 의미가 바뀜 (오른쪽→왼쪽 변경 시 분신은 원래 -1 → 새로운 -1 = Player 오른쪽 +1). **PD 명세 모호 영역** — 3단계 검증 시 PD 결정 안건. + +**PM 1차 채택**: spawn 시점 facing 고정. Player facing 변경되어도 분신 위치 (spawn 시점 기준 -1유닛) 유지. 분신의 facing은 Player flipX 동조 (시각 일관성). + +### A10-12. 변경 영향 — 기존 코드 수정 영역 + +| 파일 | 변경 | +|------|------| +| `Assets/Scripts/Skills/Effectors/CloneInstance.cs` | **신규** | +| `Assets/Scripts/Skills/Effectors/CloneEffector.cs` | **신규** | +| `Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs` | `IsCloneFireActive·CloneFireOrigin·CloneFireFacingX·CLONE_DAMAGE_MULTIPLIER` 4필드 + `OnPlayerSkillFired` 이벤트 신설 | +| `Assets/Scripts/Skills/Runtime/ActiveSkillRuntime.cs` | `Fire()` 영역 OnPlayerSkillFired 발화 1줄 + `CalculateEffectiveDamage()` 영역 50% 반감 1줄 | +| `Assets/Scripts/Skills/Events/SkillFireEvent.cs` | Minion case 영역 CardId 분기 + Cleanup 영역 IsCloneFireActive reset | +| `Assets/Scripts/Skills/Runtime/SkillRuntimeFactory.cs` | AvailableCardIds 영역 "A10" 추가 | +| `Assets/Scripts/Skills/Effectors/{ProjectileSpawner,MeleeAreaSpawner,LightningStrikeSpawner,LaserSpawner,PoisonSwampSpawner,SpiritFireSpawner}.cs` | **선택** — `IsCloneFireActive` 분기로 spawn 위치·facing 분신 origin 사용 | +| `Assets/Resources/Skills/Active/A10_bunsin.asset` | **신규** | + +**Effector 변경 최소화 옵션**: 모든 Effector에 `if (inventory.IsCloneFireActive) playerPos = inventory.CloneFireOrigin` 일관 적용. 6개 Effector × 약 3줄 = 18줄. + +**대안 = 매우 최소화 (옵션 ε)**: 분신 발동 시 PlayerSkillInventory.transform.position을 1 frame 동안 분신 위치로 swap. Effector 변경 0줄. 그러나 부작용 가능성 (다른 컴포넌트 transform 참조). **기각** — 부작용 위험. + +**채택**: 6개 Effector 일관 분기 — 명시성·안정성 우선. + +### A10-13. 기각안 + +#### A10-13-1. 분신 별도 GameObject + 자체 PlayerSkillInventory mirror — 기각 + +**기각 근거** (§A10-2 옵션 (가)): +- 코드 중복 (인벤토리·Lv·각성·이벤트 구독 2중 동기화) +- C11 자원 효율 위반 — MonoBehaviour 2중 부담 +- **채택안**: (나) — CloneInstance 단일 + Player Inventory hook + 0.5초 지연 큐 + +#### A10-13-2. Effector 한 번 호출 시 Player+Clone 2회 발동 (분신 = sprite만) — 기각 + +**기각 근거** (§A10-2 옵션 (다)): +- PD 명세 5번 "**플레이어보다 0.5초 뒤**" 직접 위반 — 즉시 2회 발동은 spec 어긋남 +- **채택안**: (나) — 0.5초 지연 큐 + 분신 위치 재호출 + +#### A10-13-3. PlayerSkillInventory.transform.position swap — 기각 + +**기각 근거** (§A10-12 옵션 ε): +- 1 frame 부작용 가능성 — Camera·HUD·다른 컴포넌트 transform 참조 영향 +- **채택안**: Effector 6개 일관 IsCloneFireActive 분기 (18줄) + +#### A10-13-4. 분신 lifetime 8초 (A11 동등) — 기각 + +**기각 근거** (§A10-1 합리적 기본값): +- v0.4 CSV "분신 1기" + "긴 주기" — 잠시 spawn 후 사라지면 "긴 주기로 1기 생성" 의미가 무너짐 +- **PD 결정 채택안 (2026-05-15)**: **12초 자동 소멸 + Singleton 1기 + BaseCooldown 25초**. 12초 내 재발동 시 기존 destroy + 새 spawn (Singleton). BaseCooldown 25 < lifetime 12 영역 활성 중 재발동 시 25초마다 갱신 +- **Lv 업 메커니즘** (PD 결정 2026-05-15): 분신 수 증가 X·추후 **지속시간 ↑ + 플레이어 참조 데미지 비율(%) ↑** (balance-designer 후속 Lv별 수치 확정) + +#### A10-13-5. 분신 facing이 Player와 독립 (분신 발동 시 적 방향) — 기각 + +**기각 근거** (§A10-1 PD 명세): +- "**플레이어 공격 패턴을 동일하게 모방**" v0.4 CSV — Player와 동일 facing이 자연 +- 분신이 적 방향 자체 추적 시 분신 = 독립 actor 의미 → §A10-2 (가) 옵션 회귀 +- **채택안**: Player facing 동조 (분신은 Player flipX와 동조) + +### A10-14. EditMode 테스트 신설 (3단계 검증 영역) + +`Assets/Tests/Editor/CloneSkillTests.cs` 신설: + +1. **CloneSpawnPosition_FacingRight_X_Minus1** — Player facing=오른쪽 시 분신 x = player.x - 1 검증 +2. **CloneSpawnPosition_FacingLeft_X_Plus1** — Player facing=왼쪽 시 분신 x = player.x + 1 검증 +3. **CloneSpriteAlpha_Is_0_5** — 분신 SpriteRenderer.color.a == 0.5f +4. **CloneDamageMultiplier_50_Percent** — Player damage 10 → Clone damage 5 검증 +5. **CloneFireDelay_0_5_Seconds** — Player Fire 시 분신 발동 시각 = Player Fire 시각 + 0.5초 (unscaledTime 기반) +6. **CloneSingleton_RespawnReplaces** — A10 재발동 시 기존 분신 destroy + 새 분신 spawn (단 1기) +7. **CloneNoRecursion_A10_FireSkipped** — 분신 자체가 A10 발동 시도 X (무한 재귀 차단) + +### A10-15. 2단계 클라이언트팀 위임 작업 단위 분해 + +**Sonnet Task 단일 위임** (C48 3자문 통과·영역 전문성·Unity C# 구현 = Sonnet 적정): + +| # | 작업 | 파일 | +|---|------|------| +| 1 | `CloneInstance.cs` 신규 — MonoBehaviour + 0.5초 지연 큐 + SpawnOrReplace 정적 메서드 + Update dequeue + OnDestroy unsubscribe | 신규 | +| 2 | `CloneEffector.cs` 신규 — IEffector 구현 + CloneInstance.SpawnOrReplace 호출 | 신규 | +| 3 | `PlayerSkillInventory.cs` 확장 — IsCloneFireActive·CloneFireOrigin·CloneFireFacingX·CLONE_DAMAGE_MULTIPLIER 4필드 + OnPlayerSkillFired 이벤트 신설 | 수정 | +| 4 | `ActiveSkillRuntime.cs` 확장 — Fire() 영역 OnPlayerSkillFired 발화 + CalculateEffectiveDamage() 영역 50% 반감 분기 | 수정 | +| 5 | `SkillFireEvent.cs` 수정 — Minion case 영역 CardId 분기 + Cleanup 영역 IsCloneFireActive reset | 수정 | +| 6 | `SkillRuntimeFactory.cs` 수정 — AvailableCardIds 영역 "A10" 추가 | 수정 | +| 7 | 6개 Effector 영역 IsCloneFireActive 분기 일관 추가 (spawn 위치·facing) | 수정 | +| 8 | `A10_bunsin.asset` 신규 — A11 동등 패턴 + A10 고유 필드 | 신규 | +| 9 | EditMode 테스트 7건 신설 | 신규 | + +**예상 작업량**: 신규 4 파일 + 수정 9 파일 + .asset 1 + 테스트 1. 단일 Sonnet Task 범위. + +### A10-16. 3단계 개발팀장 검증 항목 (사전 명시) + +1. **PD 명세 5항목 전수 정합** — 위치 (facing 반대 1유닛)·외형 (alpha 0.5)·동작 (동일 스킬)·공격력 (50% 반감)·타이밍 (0.5초 딜레이) +2. **v0.4 CSV A10 행 정합** — 분신 1기·영구 유지·동일 패턴 모방·공격력 비율 감소·무적 +3. **기존 시스템 충돌 없음** — Player Fire 정상 (분신 hook이 Player 발동 영향 X)·다른 카드 정상·BT12-Dev-Vis 13 스킬 정상 +4. **C11 정합** — 자원 효율 (CloneInstance 1기·MonoBehaviour 부담 최소)·코드 직관성 (3계층 hook 명시)·범용성 (Effector 6종 무차별 지원) +5. **EditMode 7건 + 기존 테스트 전부 green** +6. **SOT 갱신** — 스킬 이펙트 확정 SOT v1 §3 A10 추가 + §4 변경 이력 추가 +7. **PD 결정 정합 검증 (2026-05-15)** — BaseCooldown 25·MinionLifetime 12·facing 고정·무적 Collider 미부착·Lv 업 메커니즘 (분신 수 X·지속시간+데미지 비율↑) 전수 코드 정합 확증 + +--- + ## §14. 참조 문서 - **기획 SOT**: diff --git a/프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md b/프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md index 6e8621b..6dea849 100644 --- a/프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md +++ b/프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md @@ -139,6 +139,31 @@ HitFxScale=0.5 FxRotation=0 OffsetXY=(0,0) DamageFrameDelay=0 EnableRepeatDamage=0 MaxHitCount=1 RepeatFrameInterval=30 ``` +### A10 분신 (Clone·Category 3 Summon·CloneEffector·BT12-Dev-Clone 2026-05-15·PD 결정 stamp 2026-05-15) +``` +BaseCooldown=25 BaseDamage=0 HitboxSize=(0, 0) OffsetDistance=(0, 0) +Trajectory=0 MinionLifetime=12 (12초 지속·Singleton 1기·PD 직접 결정 2026-05-15) +AttributeTags=0 TypeTags=0 +ProjectilePrefab=null OnHitFxPrefab=null ExtraHitFxPrefab=null CastFxPrefab=null +OnDotFxPrefab=null +DotDuration=0 DotInterval=0.5 +HitFxScale=1 FxRotation=0 OffsetXY=(0,0) +DamageFrameDelay=0 EnableRepeatDamage=0 MaxHitCount=1 RepeatFrameInterval=30 +# PD 명세 5항목 (코드 하드코딩 영역·.asset 영역 변경 불요): +# - spawn 위치: facing 반대 1유닛 (CloneInstance.SpawnOrReplace·facing 고정) +# - sprite alpha: 0.5 +# - 동일 스킬 사용: OnPlayerSkillFired hook (PlayerSkillInventory) +# - damage 50% 반감: ActiveSkillRuntime.CalculateEffectiveDamage + IsCloneFireActive 분기 +# - 0.5초 딜레이: CloneInstance._pendingQueue (unscaledTime 기반) +# PD 2026-05-15 직접 결정 4건: +# - BaseCooldown 25초 (PM 1차 30초 → PD 조정 25초) +# - MinionLifetime 12초 (영구 1기 → 12초 자동 소멸·Singleton 유지) +# - facing 고정 (spawn 시점 facing 고정·Player 이동 시 분신 위치·방향 불변) +# - 무적 = Collider 미부착 (적 투사체·벽·player·enemy 모두 통과) +# - Lv 업 시 분신 수 증가 X · 추후 지속시간↑+플레이어 참조 데미지 비율(%)↑ (balance-designer 후속 수치 확정) +# BaseDamage 0 = 분신 자체 damage X (Effector 재호출 시 Player damage * 0.5) +``` + ### A_Laser 용염 레이저 (Dragonfire Laser·Category 1 MeleeArea·LaserSpawner) ``` BaseCooldown=3 BaseDamage=5 HitboxSize=(10, 1.2) OffsetDistance=(-0.4, -0.1) @@ -155,6 +180,8 @@ DamageFrameDelay=10 EnableRepeatDamage=1 MaxHitCount=7 RepeatFrameInterval=10 |---|---|---| | 2026-05-14 | 본 SOT 신설 (확정 stamp) | `1a1de0c` | | 2026-05-14 | A06·A11 박스 시각화 추가 (PoisonSwampHitbox_Debug·SpiritFireHitbox_Debug) · A11 OverlapBox 전환 (HitboxSize 사용) · A11 DotInterval 기반 피해 간격 · A11 소멸 0.5초 전 페이드 (alpha 1→0·scale 1→0.5) — PD 발화 정합 | (본 commit) | +| 2026-05-15 | **§3 A10 분신 (Clone) 신설** — Category 3 Summon · CloneEffector + CloneInstance + PlayerSkillInventory.OnPlayerSkillFired hook + 0.5초 지연 큐 + IsCloneFireActive 분기 (damage 50% 반감) · spawn 위치 facing 반대 1유닛 · sprite alpha 0.5 · BaseCooldown 30 PM 1차 추정. BT12-Dev-Clone PD 명세 5항목 정합 + C49 1단계 (개발팀장 Opus 설계) 시범 | (후속 EerieVillage commit) | +| 2026-05-15 | **§3 A10 PD 결정 4건 반영** — BaseCooldown 30→25·MinionLifetime 0(영구)→12초 자동 소멸·facing 고정·무적 Collider 미부착·Lv 업 시 분신 수 X·지속시간+데미지 비율(%) ↑ (balance 후속). BT12-Dev-Clone PD 직접 결정 2026-05-15 | (후속 EerieVillage commit) | ---