PD 보고 2건:
1. 분신 영역 투사체 영역 영역 영역 영역 영역 X
원인: _spawnFacingX 영역 spawn 시점 영역 영역 영역 → Player facing 변경 후 분신 발동 시 영역 영역 영역 영역 영역 영역
fix: SyncSpriteAndPosition 영역 매 frame _spawnFacingX 영역 영역 영역 (pc.Facing 영역)
→ 분신 발동 시 CloneFireFacingX = _spawnFacingX (영역 영역 영역 영역) → 투사체 정합 영역
PD 결정 4번 (facing 고정) 영역 — 분신 영역 영역 영역 영역 영역 영역 영역 (시각 영역 영역 영역 — 직전 fix 영역 영역) → facing 영역 영역 영역
2. Player hit·death 영역 분신 영역 영역 영역 (잔존 현상)
원인: CloneInstance.Update 영역 lifetime 12초 영역 영역 영역 → Player 영역 영역 영역 영역 분신 영역
fix: Update 영역 매 frame Health.IsAlive 영역 영역 → false 영역 분신 즉시 Destroy(gameObject)
+ _playerInventory == null 영역 영역 destroy (Player.gameObject Destroy 영역 영역)
MCP 검증: refresh_unity + read_console errors 0
PD 보고: '이동할 때 분신의 방향이 반대로 뒤집혀버렸어. (방향전환 할 때는 자연스러움)'
원인: 분신 flipX 영역 = deltaX < 0 영역 영역 (이동 방향 영역 영역)
- Player 영역 영역 영역 영역 영역 영역 영역 → 분신 영역 영역 영역 영역 영역 영역 영역 영역 영역 → deltaX < 0 → flipX = true → 영역 영역 sprite
- Player.flipX 영역 영역 영역 영역 (이미 영역 영역 sprite + flipX true 영역 영역 영역) → 분신 영역 flipX 영역 영역 영역 → 영역 영역
근본 fix: 분신 flipX 영역 = _playerSr.flipX 영역 즉시 동조
- PlayerController L306·311 영역 spriteRenderer.flipX 변경 → 분신 영역 직접 영역
- 분신 sprite (Player Animator frame) + flipX 영역 영역 Player 영역 영역 영역 영역 영역 영역
- 방향 전환 자연 영역 = 분신 영역 영역 영역 영역 (MoveTowards) 영역 영역 영역 (flipX 영역 영역 X)
MCP 검증: refresh_unity + read_console errors 0
PD 보고 2건:
1. Player 영역 영역 → 분신 영역 영역 영역 영역 영역 → 영역 영역 영역
원인: 분신 영역 = Player root 자식 부착 영역 → Player.localScale 영역 영역 영역 영역 분신 lossyScale 영역 영역 영역 영역 영역
fix: SetParent X · 독립 GameObject + 매 frame Player worldPos + offset 영역 영역
분신 flipX = 이동 방향 영역 영역 영역 (deltaX 영역) → 자연 영역 영역
2. 영역 영역 영역 영역 영역 (영역 영역 영역 영역 영역) + 달리는 영역 영역 영역
fix: SPAWN_OFFSET_X 1.0 → 0.5 (50% 영역)
sprite 영역 매 frame 영역 (_cloneSr.sprite = _playerSr.sprite) Animator frame 영역 영역 영역
CloneInstance 정정:
- SPAWN_OFFSET_X 0.5 (50% 영역)
- SpawnOrReplace: SetParent X · transform.position = playerPos + offset · localScale = PlayerSr.lossyScale (Player 영역 동일)
- SyncSpriteAndPosition: worldPos target 영역 영역 · MoveTowards · sprite 영역 · flipX 영역 영역 영역 영역
MCP 검증: refresh_unity + read_console errors 0
PD 보고: '분신 영역 영역 영역 영역 영역 영역. 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역.'
원인: SyncSpriteAndPosition 영역 매 frame _cloneSr.flipX = _playerSr.flipX 영역 영역
- Player 영역 영역 영역 영역 즉시 영역 영역 → 분신 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역
- 분신 영역 sprite 영역 영역 → 영역 영역 영역 영역 영역 영역 영역 영역
fix: 분신 flipX 영역 = 이동 방향 영역 영역 영역
- deltaX > 0 (영역 영역 영역) → flipX = false (영역 영역 영역)
- deltaX < 0 (영역 영역 영역) → flipX = true (영역 영역 영역)
- 영역 영역 (deltaX = 0) → Player flipX 영역 영역 (영역 영역 영역 정합)
영역: Player 영역 영역 영역 영역 영역 영역 영역 → 분신 영역 (target 영역 영역) 영역 영역 영역 영역 영역 영역 영역 영역 영역 영역 → Player 영역 영역 영역 영역 → 분신 영역 영역 영역 영역 → target 영역 영역 영역
MCP 검증: refresh_unity + read_console errors 0
원인: 분신 영역 Player root 자식 부착 영역 + localScale = playerSr.transform.localScale 영역 영역
- PlayerSr 영역 영역 영역 영역 영역 영역 (예: Player → SpriteHolder → PlayerSr) 영역 영역 영역 영역 영역 자식 영역 영역 localScale 영역 영역 영역 X
- 분신 lossyScale = playerInventory.lossyScale * playerSr.localScale 영역 영역 PlayerSr.lossyScale 영역 영역 영역 영역 영역
fix: PlayerSr.lossyScale 영역 동일 영역 영역 분신 localScale 영역 정확 계산
- 분신 lossyScale = playerInv.lossyScale * localScale ← PlayerSr.lossyScale 동일 영역 영역
- 영역: localScale = PlayerSr.lossyScale / playerInv.lossyScale (각 축 영역)
- 0 나누기 영역 fallback Vector3.one (안전망)
MCP 검증: refresh_unity + read_console errors 0
FIRE_DELAY_SECONDS = 0.5f → 0.25f
- PD 명세 5번 원본 (0.5초) → PD 본 영역 영역 영역 0.25초 단축
- 분신 영역 Player 영역 영역 영역 더 빠른 영역 동일 스킬 미러링
MCP 검증: refresh_unity + read_console errors 0
PD 영역 영역 2건:
1. 분신 영역 Player 영역 영역 (이동·대기·idle·run 영역) 영역 영역 영역 영역
→ 매 frame _cloneSr.sprite = _playerSr.sprite + flipX 동조 (Animator frame 영역 영역 영역 영역 영역 영역 영역)
2. Player facing 변경 시 분신 위치 자연 영역 (순간 이동 X·걸어서 뒤로 가는 영역)
→ _targetLocalPos 영역 매 frame 갱신 (facing 영역 영역 영역) + Vector3.MoveTowards (MOVE_SPEED=3f) 영역 영역 영역
CloneInstance 정정:
- 신규 필드: _cloneSr·_playerSr·_targetLocalPos·MOVE_SPEED 상수
- SpawnOrReplace: cloneSr 영역 변수 영역 + instance 초기화 영역 sr 참조 저장
- Update: SyncSpriteAndPosition() 매 frame 호출 (lifetime·queue 영역 영역 영역)
- SyncSpriteAndPosition: sprite·flipX 매 frame 동조 + facing 기반 target 갱신 + MoveTowards 영역 영역 영역
PD 결정 4번 (facing 고정) 정합 — 분신 발동 영역 facing = spawn 시점 _spawnFacingX 영역 영역. sprite·위치 영역 영역 = 동조 영역.
MCP 검증: refresh_unity + read_console errors 0 (compile 통과)
PD 보고 (2026-05-18) 3건:
1. 분신 영역 Player 영역 영역 X (생성 시점 고정) → Player 자식 부착 (SetParent worldPositionStays=false) + localPosition (-signX, 0, 0) 영역 동조
2. 분신 영역 공격 X → Test Fire(idx) 영역 _inventory.RaisePlayerSkillFired(rt) 발화 영역 추가
- 원인: Test 영역 직접 Effector.Trigger 호출 영역 ActiveSkillRuntime.Fire 영역 영역 X·OnPlayerSkillFired 발화 X
- fix: Fire(idx) 끝 영역 IsCloneFireActive 분기 + RaisePlayerSkillFired 발화 (분신 hook 영역 미러링 발동)
3. 분신 영역 크기 영역 영역 작아 영역 → localScale = playerSr.transform.localScale 영역 정합
- 원인: 분신 GameObject 영역 localScale (1,1,1) 영역 영역·PlayerSr 자식 영역 localScale 영역 영역 X 영역 영역 영역 영역 영역
- fix: PlayerSr 자식 영역 localScale 영역 영역 (자식 lossyScale 영역 영역 영역 영역)
MCP 검증: refresh_unity + read_console errors 0 (compile 통과)
PD 지시 2026-05-18: '분신 스킬을 1번키를 누르면 사용가능하도록 해줘.'
TestSkillFireOn1to5 정정:
- EnsureRuntimes 영역 Skill1 강제 A10_bunsin Resources.Load (Inspector 영역 무관·항상 A10 영역)
- Fire(idx) Minion case 영역 A10 CardId 영역 CloneEffector 영역 분기 (SkillFireEvent.Execute 동일 패턴)
- CloneEffector 멤버 readonly 추가
MCP 검증: refresh_unity + read_console errors 0 (compile 통과)
PD 지시: '판정 체크 영역 영역 영역 영역 붉은 박스 영역 영역 영역 시각화 영역 영역 영역 영역 영역.'
- HitboxDebug.ShowDebugVisuals = true → false
- 모든 액티브 스킬 영역 SpriteRenderer.enabled = ShowDebugVisuals 영역 자동 정합 (Projectile·LightningStrike·MeleeArea·Laser·PoisonSwamp·SpiritFire·Range)
- BT12-Dev-Vis 영역 toggle 메커니즘 영역 활용 (PD 지시 2026-05-13 영역)
MCP 검증: refresh_unity + read_console errors 0 (true→false 단순 상수)
CS0117·CS1061 영역 fix — Test assembly 영역 main 영역 internal 영역 접근 X:
- IsCloneFireActive·CloneFireOrigin·CloneFireFacingX·CLONE_DAMAGE_MULTIPLIER 4건 internal → public
MCP 검증 정합:
- refresh_unity (compile=request) → 컴파일 오류 0
- run_tests EditMode CloneSkillTests → 7/7 passed (0.7초·T01~T07 전수 green)
본 PM 자성 #5 누적 (C39-10): Test assembly 영역 internal 접근 영역 사전 실측 X (BT12-Dev-Clone α·β 영역 internal 영역 정의 시점)
OnPlayerSkillFired event 영역 외부 클래스 .Invoke() 직접 호출 불가 (C# event 의미 영역):
- PlayerSkillInventory: RaisePlayerSkillFired(runtime) public 메서드 추가 — 내부 OnPlayerSkillFired?.Invoke 영역 캡슐화
- ActiveSkillRuntime.Fire: _inventory.OnPlayerSkillFired?.Invoke(this) → _inventory.RaisePlayerSkillFired(this) 정정
본 PM 자성 #4 (C39-10 누적·feedback_new_code_existing_system_dependency_unmeasured 4회차):
- #1 CloneInstance namespace 추정 (Events 부재)
- #2 asmdef autoReferenced 영역 추정 (main reference 자동 X)
- #3 asmdef 메커니즘 사전 동작 검증 X (default assembly 격리)
- #4 C# event 외부 invoke 불가 영역 사전 실측 X
CloneInstance 영역 += -= 영역 정합 (구독·해제) — 정정 대상 X
CS0234 EerieVillage.Skills.Effectors namespace 부재 근본 fix:
- 원인: asmdef autoReferenced=true 영역도 main Assembly-CSharp 영역 reference X (asmdef 메커니즘 영역 default assembly 영역 격리)
- 본 PM 자성 #3 누적 (C39-10 위반·asmdef 영역 사전 동작 영역 추정)
- fix: asmdef + .meta 삭제 → Tests/Editor 영역 default Assembly-CSharp-Editor 영역 자동 흡수 → main Assembly-CSharp (CloneInstance·PlayerSkillInventory 등) 자동 reference
- NUnit: default Editor assembly 영역 Unity Test Framework 자동 reference 영역 (UNITY_INCLUDE_TESTS 영역 정합)
PD Editor Refresh 시 Test Runner CloneSkillTests 7건 자동 인식 영역 (default Assembly-CSharp-Editor 영역 NUnit 영역 정합)
CS0234 EerieVillage.Skills.Effectors namespace 부재 fix:
- 원인: asmdef overrideReferences=true·autoReferenced=false 영역 main Assembly-CSharp 차단
- fix: overrideReferences=false·precompiledReferences=[]·autoReferenced=true
- 결과: Test assembly 영역 default Assembly-CSharp 자동 reference (CloneInstance·PlayerSkillInventory 접근 OK)
- NUnit 영역 TestRunner reference 영역 정합 (UNITY_INCLUDE_TESTS define 유지)
자성: C39-10 위반 누적 (asmdef 영역 사전 실측 X·feedback_new_code_existing_system_dependency_unmeasured 재발 2회차)
CS0234 컴파일 오류 fix:
- 본 PM 추정 오류 — SkillFireEvent namespace = EerieVillage.Skills (.Events 영역 X)
- CloneInstance.cs L202 영역 EerieVillage.Skills.Events.SkillFireEvent → SkillFireEvent 단순화
- parent namespace EerieVillage.Skills 자동 인식 (CloneInstance namespace = EerieVillage.Skills.Effectors)
자성: C39-10 위반 (신규 코드 영역 기존 시스템 namespace 사전 실측 X·feedback_new_code_existing_system_dependency_unmeasured 재발)
PD 발화: "몬스터 판정 영역을 제거해줘."
EnemyController.OnDrawGizmos 폐기:
- VisualBounds wire cube (붉은색) 제거
- _collider.bounds wire cube (노란색) 제거
- Application.isPlaying 시점 Editor Scene 보조선만 출력하던 영역 정합
게임 동작 (Update Player ↔ Enemy 충돌 판정·Decrement) 영역 영향 X.
Editor Scene 영역 wire cube 시각만 사라짐.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 발화: "독늪이 플레이어 위치에서 생성될 경우 플레이어의 Y값에서
-0.5가 아니라 -0.2 아래의 위치에 생겨야할거 같아"
직전 commit 664607a 수치 조정만:
spawnPos.y = playerPos.y - 0.5 + OffsetXY.y
↓
spawnPos.y = playerPos.y - 0.2 + OffsetXY.y
OffsetXY (PD Inspector 미세 조정 영역)은 그대로 유지.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 보고: "독늪이 플레이어 위치에서 생성될 경우 플레이어의 Y값에서
-0.5정도 아래의 위치에 생겨야할거 같아"
직전 commit 3c5a3bc 의 Player fallback ground Raycast 영역 — Player
ground 위 발판 hit (예: -2.61) → spawn 위치 ground 표면. PD 의도는
Player.y - 0.5 직접 (시각 정합·발 아래 한 키 정도).
분기 정정:
- nearest != null (지상 Enemy 후보): Enemy 위치 ground Raycast (기존 영역)
- nearest == null (공격 가능 적 없음·Player fallback):
spawnPos = (playerPos.x + OffsetXY.x, playerPos.y - 0.5 + OffsetXY.y)
· ground Raycast 폐기 · PD 명시 수치 직접
검증 (Play 모드):
- 비박쥐 13기 사망 + 박쥐 1기만 (IsFlying skip)
- Player pos=(-15.14, -2.21) · OffsetXY=(0, -0.4)
- Swamp pos=(-15.14, -3.11) = Player.y - 0.5 + OffsetXY.y(-0.4) 정합
OffsetXY는 PD Inspector 추가 미세 조정 영역 (현 -0.4).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 추가 보고: "여전히 독 늪이 공중 몬스터의 Y 위치에 발생되고 있어.
공격 가능한 적이 없을 경우(공중 몬스터만 있을 경우 등) 독 늪이
플레이어 X 위치에서 이동 가능한 영역 바닥에 생성 되도록 해줘."
원인: 직전 commit 2516ef9 의 e.IsFlying check 영역 — Enemy.Awake/Start
호출 순서·controller late assign race 시 IsFlying=false 잔존 가능 →
박쥐 nearest 후보 영역 → 박쥐 y 위치 spawn (Raycast hit 후 ground y 사용
하더라도 박쥐가 ground 위에 있다면 박쥐 위치 그대로).
정정: PoisonSwampSpawner.Trigger 루프 영역 e.RecheckFlyingFromAnimator()
강제 호출. Animator.runtimeAnimatorController.name 영역 flyingControllerNames
list 매칭 → IsFlying 즉시 갱신.
검증 시나리오 (Play 모드):
- 비박쥐 Enemy 13기 사망 처리 (Player 주변 박쥐 1기만 남김)
- 박쥐 1기 IsFlying=True 정합
- A06 발사 → spawn pos=(-15.14, -2.61) = Player.x(-15.14) + ground.y(-2.61)
- 박쥐 y=-2.00 위치 영역 spawn 안 됨 (차단 정합)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 보고: "독 늪은 공중에 생성 되지 않도록 수정해줘. (플레이어나
몬스터가 밟고 이동할 수 있는 영역에만 생성 가능해야 함)"
정정 PoisonSwampSpawner.Trigger:
1. nearest Enemy 탐색에서 IsFlying=true (박쥐 등) skip
- 공중 박쥐 위치 spawn 후보 제외
2. spawn 후보 (nearest 또는 Player 위치 + OffsetXY) 에서
Vector2.down Raycast (거리 20, groundLayerMask Layer 0 + Layer 16)
3. Raycast hit X → return (spawn 차단)
4. Raycast hit O → spawnPos.y = groundHit.point.y (ground 표면 위)
groundLayerMask = (1 << 0) | (1 << 16):
- Layer 0 : Level Tilemap (메인 ground)
- Layer 16: Floating 발판 (Foreground)
검증 (Play 모드):
- 시나리오 1 (Player 지면): spawn 1기·pos.y=-2.88 (ground 위)
- 시나리오 2 (Player y=50 공중·모든 Enemy IsFlying): spawn 증가 0 (차단)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 결정: "B안으로 진행해" (Inspector 단일 수치·전 박쥐 일괄·확장 일관)
EnemyController.flyingYOffset float Inspector (기본 2f) 신설.
IsFlying=true 첫 set 시 transform.position.y += flyingYOffset 자동
적용 (_flyingOffsetApplied flag 영역 중복 적용 차단).
- Awake / Start / MonsterRandomizer.Awake 영역 다중 호출 케이스에서도
1회만 적용
- Rigidbody2D.position 동시 갱신 (KinematicObject 정합)
- _startY 갱신 (fallThreshold 기준점·IsFlying=true 영역 skip 안전망)
검증 (Play 모드):
- 박쥐 3기 모두 flyingYOffset=2 적용
- pos.y: -2.00·-1.90·-1.90 → 0.00·0.10·0.10 (지면 +2 정합)
PD Inspector flyingYOffset 영역 수치 조절로 박쥐 높이 변경 가능.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 지적: "enemy 랜덤풀에 플라잉 몬스터를 설정하는게 아니라
개별 몬스터 특성에 플라잉 속성을 부여해야하지 않을까?"
직전 commit 60c2e9b 의 2 위치 분산 (MonsterRandomizer.flyingFlags +
EnemyController hardcoded "M002") 정정. SOT 단일화.
설계:
- EnemyController.flyingControllerNames string[] (Inspector 기본
{ "M002" }) — 개별 몬스터 특성 IsFlying 속성 단일 SOT
- EnemyController.RecheckFlyingFromAnimator() public method 신설
· Animator.runtimeAnimatorController.name 영역 flyingControllerNames
list 매칭 → IsFlying=true 자동
· control.gravityModifier=0·velocity=0·ignoreCollisions=true 일괄
- EnemyController.Awake + Start 영역 RecheckFlyingFromAnimator 호출
- MonsterRandomizer.Awake 영역 controller random 후 위임 호출만
폐기:
- MonsterRandomizer.flyingFlags bool[] (분산 SOT 폐기)
- MonsterRandomizer name fallback "M002" hardcoded (분산 폐기)
- EnemyController.Awake 직접 hardcoded "M002" check (분산 폐기)
확장: 후속 공중 몬스터 추가 (예: 까마귀 M005) 시 PD Inspector
flyingControllerNames 배열에 controller name 추가만 하면 자동 적용.
검증 (Play 모드):
- 총 Enemy 16기 · M002 박쥐 3기 모두 IsFlying=True
- M005 등 비박쥐 IsFlying=False · gravMod=1 (지상 정상)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 추가 보고 + 스크린샷: "여전히 박쥐 몬스터가 공중에 떠있지 않고
움직이지도 않아"
진단 결과: Enemy.prefab 영역 MonsterRandomizer 부착 X · Animator
직접 M002.overrideController 부착. 직전 commit 6be8ccd 의
MonsterRandomizer flyingFlags / name fallback 영역 발화 X →
IsFlying=False 잔존 → gravity·collide 정상 적용 → 박쥐 지상 정지.
정정:
- EnemyController.Awake 영역 Animator.runtimeAnimatorController.name
"M002" 포함 시 IsFlying=true 자동 set
- 기존 MonsterRandomizer name fallback 도 보존 (랜덤 케이스 대비)
검증 (Play 모드):
- Enemy 16기 중 박쥐 3기 모두 IsFlying=True·ignoreCollisions=True·
gravMod=0 자동 set
- 1기 velocity=(-3.50, 0) patrol 이동 중·2~3기 wait 상태 정합
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 추가 보고: "공중에 체공하게 한 몬스터가 여전히 이동하지 않아"
원인: 직전 commit 40600da (gravity 0·cliffCheck skip·fallThreshold skip)
후에도 transform.position x 변동 0. velocity=(-3.50, 0) 정상이나 실제
이동 X. KinematicObject.PerformMovement body.Cast 영역 발판·기타
collider hit → distance reduce → body.position += move * 0 → 이동 0.
정정:
1. KinematicObject.ignoreCollisions bool 신설.
FixedUpdate 영역 ignoreCollisions=true 시 Cast skip:
body.position += velocity * Time.deltaTime 단순 이동.
2. EnemyController.Awake + Start 영역 IsFlying=true 시 control.ignoreCollisions=true 자동 set.
Start 영역 보강 — MonsterRandomizer.Awake → IsFlying=true set 시점이
EnemyController.Awake 이후 케이스 (Unity Awake 호출 순서 무관 보장).
검증 (Play 모드 3초):
- [t=0] pos=(-15.20, 0.50) ignoreCollisions=True
- [t=3s] pos=(-18.94, 0.50) velocity=(-3.50, 0) — x Δ=-3.74 이동·y 유지
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 보고:
1. "Enemy_M002_Bat 몬스터는 날으는 몬스터이기 때문에 y위치를 높이고
싶은데 자꾸 땅으로 내려오는 현상을 수정해줘."
2. "이 몬스터가 이동하지 못하는 이유를 체크해보고 수정해줘."
원인 진단:
1. KinematicObject.FixedUpdate L107 else 분기 (velocity.y>=0)
gravityModifier 무시·무조건 Physics2D.gravity 적용
→ 박쥐 gravityModifier=0 해도 천천히 떨어짐
2. EnemyController.UpdatePatrol cliffCheck Raycast 영역 공중 박쥐
발 밑 ground 없음 → 즉시 TriggerReverse → 1초 cooldown 후 다시
검출 → 무한 좌우 반전 → 이동 0
3. EnemyController.Update L361 fallThreshold 떨어짐 검출
→ 강제 텔레포트 _startY 복귀
정정:
1. KinematicObject.FixedUpdate else 분기에도 gravityModifier 곱
gravityModifier=0 → 자연 중력 무효 (Player gravityModifier=1 영역
영향 X·기존 동작 보존)
2. EnemyController.IsFlying bool 신규 (Inspector)
- Awake 영역 IsFlying=true → control.gravityModifier=0·velocity=0
- UpdatePatrol cliffCheck 영역 !IsFlying 분기 (cliff skip)
- Update 떨어짐 텔레포트 영역 !IsFlying 분기 (skip)
3. MonsterRandomizer.flyingFlags bool[] 신규 (Inspector·동일 length)
- Awake 영역 random idx · flyingFlags[idx]=true → EnemyController.IsFlying=true 자동 set
검증 (Play 모드):
- IsFlying=true 강제 set + y +3 이동
- [t=0] pos.y=0.50 · gravMod=0
- [t=3s] pos.y=0.50 (유지·떨어짐 X) · velocity=(-3.50, 0) (x patrol 이동·y 0)
PD 후속: Enemy.prefab Inspector MonsterRandomizer.flyingFlags 영역
박쥐 (M002) idx 영역 true 설정 필요.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 보고: "정령불의 피격 범위에 있는 적은 EnableRepeatDamage가
체크되어있는데도 피해를 받지 않고 있어"
직접 진단 — Play 모드 [SpiritFire][Tick] Debug.Log 측정:
- 박스 center·size 정합 · OverlapBox enemyHit=1·dmg=5 6회 호출 확인
- A11 hit·damage 자체는 정상 동작
진짜 원인: DecrementBypassInvuln (DoT 함수·hit 모션·flash 발화 X)
호출. Enemy maxHP=99999 → 매 초 5 감소 = 시각상 변화 X·hit flash X
→ PD 인식상 "피해 X".
정정:
- DecrementBypassInvuln → DecrementBypassInvulnWithHit
- A05·Laser·Lightning·MeleeArea 동일 패턴 (hit 모션 + 붉은 flash 1f)
- A06 PoisonedEnemyMarker 영역 DoT 표현 의도라 DecrementBypassInvuln 유지
부속:
- 진단 Debug.Log 회수 (목적 달성)
검증 (Play 모드 직전 측정·진단 회수 전):
- center=(-13.81, -2.28) totalHit=3 enemyHit=1 dmg=5 (6회 연속 출력)
- A11 매 DotInterval 1초 hit 정합
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 요청:
1. 정화의 빛 (A12) 판정 범위 2개 필요
2. 모든 스킬 영역 — 체크박스로 추가 판정 범위 지정 가능
ActiveSkillData 신규 필드 (Header "2차 판정 박스 (선택)"):
- bool EnableSecondHitbox 체크박스 (기본 false)
- Vector2 SecondHitboxSize (기본 (1.5, 1.0))
- Vector2 SecondOffsetDistance (기본 (0, 0))
MeleeAreaSpawner.cs 분리·일반화:
- SpawnHitboxVisual static helper 신규 (1차·2차 박스 공통)
- DoOverlapBoxAt static helper 신규 (1차·2차 판정 공통)
- Trigger 영역 EnableSecondHitbox 분기 → 2차 박스·이펙트 위치 spawn
- DoOverlapBoxFromPlayer 영역 EnableSecondHitbox 분기 → 2차 판정 위치 OverlapBox
- facing sign 1차·2차 동일 적용 (좌/우 일관 반전)
A12_jeonghwauibit.asset placeholder (PD Inspector 미세 조정 가능):
- HitboxSize: (4,4) → (1.5, 5) 1차 vertical 줄기
- OffsetDistance: (0,0) → (0, 3) Player 위쪽 3
- EnableSecondHitbox: 1
- SecondHitboxSize: (1.5, 5) 2차 vertical 줄기
- SecondOffsetDistance: (0, -3) Player 아래쪽 3
검증 (Play 모드):
- A12 발사 → MeleeHitbox_Debug + MeleeHitbox_Debug2 동시 spawn
- 1차 pos.y = Player(-2.18) + offset.y(+3) = 0.82 ✓
- 2차 pos.y = Player(-2.18) + offset.y(-3) = -5.18 ✓
- 각 박스 scale = (1.5, 5) vertical 줄기 정합
후속: Laser·Lightning·Projectile spawner 영역 SecondHitbox 적용은
PD 요청 발생 시점에 동일 패턴 (Helper extract → 2차 분기) 정합.
공통 필드는 본 commit 으로 일괄 추가.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 보고 + Console 로그 결정적:
"[Projectile][WallHit-OnTrigger] cardId=A02 other=PoisonSwamp_Collider
parent=FX_Venom_Swamp(Clone) layer=0(Default) isTrigger=True
pos=(-7.30, -0.30, 0.00) dist=5.00/8"
원인: 직전 commit 708ba08 isWall = (Layer 0) 정정 후에도 A06 독 늪
PoisonSwamp_Collider (Layer 0 + isTrigger=true) 가 Wall 판정 통과 →
빠른 투사체 (A02 dist=5/8 = 62.5%) 조기 SelfDestruct.
느린 A13 정상은 0.1초 grace 통과 + 짧은 거리 우연 회피.
정정:
- isWall = (Layer 0) && !other.isTrigger
- Level Tilemap (non-trigger) 만 Wall 차단
- Effector spawn trigger collider (A06 독 늪·CinemachineConfiner·
Token·DeathZone·기타 Layer 0 Trigger) 모두 통과
Wall OverlapPoint (Update L186) 영역 이미 filter.useTriggers=false 로
trigger 제외 정합 — 변경 불필요.
진단 Debug.Log 2건 회수 (목적 달성).
검증 (PD Play 확인 필요):
- A02 (속도 6)·A08·A14·A15 빠른 투사체 MaxRange 까지 정상 비행
- 독 늪 범위 통과
- Level Tilemap 벽 충돌 시 SelfDestruct 유지
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 보고 2건:
1. "투사체 판정 범위를 다시 보여줘"
2. "파이어볼이나 저주의 화살과 같은 투사체 형태는 여전히 맵이
연결되는 경계선을 넘지 못하고 제자리에서 멈추다가 소멸하고 있어.
(단, 속도가 느린 투사체는 정상적으로 날아감)"
정정:
1. HitboxDebug.ShowDebugVisuals false → true
- Range_Debug (파란 박스)·ProjectileHitbox_Debug (붉은 박스)·
LaserHitbox_Debug·MeleeHitbox_Debug·Hitbox_Debug 일괄 노출.
- SpriteRenderer.enabled toggle 만 — GameObject·LiveHitboxSync 부착 정상.
2. Projectile.OnTriggerEnter2D Wall hit 시 + Update Wall OverlapPoint
hit 시 진단 Debug.Log 추가:
- [Projectile][WallHit-OnTrigger] cardId·other.name·parent·layer·
isTrigger·pos·dist/maxRange
- [Projectile][WallHit-OverlapPoint] cardId·hit.name·parent·layer·
pos·dist/maxRange
PD Play 후 Console "[Projectile][WallHit-*]" 로그 + 박스 시각으로
어떤 collider 가 빠른 투사체 (A02·A08·A14·A15) 를 차단하는지
정확 식별. 본 PM 후속 정정 시 회수 의무.
원인 가설: 직전 commit 708ba08 Layer 16 제외 후에도 잔존 →
다른 collider (CinemachineConfiner Trigger·InfiniteHorizontalGround
Left/Right 자식·Background segment 등) hit 가능성.
A13 (속도 2.5) 정상·A02 (속도 6)·A08 영역 차단 — 빠른 투사체에서만
재현 패턴 정합.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 추가 진단 (스크린샷 + 발화): "게임 플레이 후 스크롤 되는 맵에
여전히 남아있는 상태야. 아마 스크롤 되며 연장되는 맵 영역이
초기화 되지 않는 것으로 예상 돼"
이전 commit ea239fe (3중 진입점 + FX clone prefix) 의 catch 누락
가능성 차단:
1. PlayerSkillInventory.DoCleanupStalePooledSpawns 영역
Resources.FindObjectsOfTypeAll → Scene.GetRootGameObjects + 재귀
변경. hideFlags hidden GO 누락 우려 제거·정확도 향상.
CollectStaleRecursive 신규 — 자식 트리 재귀 탐색.
IsStaleByName 헬퍼 — 이름 매칭 통합.
2. Projectile.Awake 신규 — _data == null && _runtime == null 상태
(= Initialize 미호출 잔존) 시 1 frame 유예 후 자기 destroy.
PlayerSkillInventory cleanup 누락 케이스 자체 정리 (2중 방어).
InfiniteHorizontalBackground·기타 컴포넌트 자식 부착된 잔존도
본 자가 destroy 로 catch.
측정 (Play 진입 직후):
- AfterSceneLoad static cleanup removed=0
- Awake cleanup removed=0
→ 이전 Play 잔존 = 0건 (Scene load·Awake 시점)
→ Hierarchy 영역 시각상 spawn = 자동 발사 진행 결과
후속: PD Refresh + Play → 화면 잔존 재확인 필요.
잔존 시 Console "[PlayerSkillInventory] ... removed=N" 로그 +
스크린샷 으로 본 PM 추가 진단.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 추가 보고: "여전히 씬을 실행할 때 이전에 생성 된 풀링 오브젝트가 남아있어"
직전 commit 01865b8 Awake cleanup 1회만 호출 — 진입점 보강.
강화 사항:
1. RuntimeInitializeOnLoadMethod(AfterSceneLoad) 정적 cleanup 추가
— Awake 보다 선행하는 Scene load 직후 진입점.
2. Awake cleanup 무조건 Debug.Log (removed=0 케이스도 호출 확인 가능).
3. DelayedCleanupCoroutine — Awake 후 1·3·10 frame 추가 cleanup
(다른 컴포넌트 Awake/Start spawn 케이스 catch).
4. StaleClonePrefixes 신규 — FX clone 7종 prefix 매칭
(FX_Fireball_Bullet·FX_Lightningball·FX_Dragonfire·FX_Thunder·
FX_SLASH·FX_PinkMagicArrow·Projectile_*).
5. DoCleanupStalePooledSpawns static 메서드 통합 — useImmediate 옵션
(정적 호출 시 DestroyImmediate·Awake 호출 시 Destroy).
측정 (Play 진입 직후):
- AfterSceneLoad static cleanup removed=0
- Awake cleanup removed=0
→ 이전 Play 잔존은 0건. Hierarchy 영역 보이는 spawn 은
현재 Play 의 정상 자동 발사 결과 (BaseCooldown Tick spawn) 로 추정.
후속: PD 재현 시나리오 (Stop→Play 또는 Editor crash 후 재실행 등)
직접 확인 필요. Console 영역 "[PlayerSkillInventory] ... removed=" 로그로
cleanup 호출·잔존 카운트 확인 가능.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PD 보고: "게임 플레이 중 종료했다가 다시 시작할 경우 이전 게임
플레이 중 생성 된 투사체가 여전히 남아있어. 게임을 재실행할 때
기존에 생성 된 풀링 오브젝트가 소멸될 수 있도록 수정해줘."
PlayerSkillInventory.Awake 시점 CleanupStalePooledSpawns 호출:
- Projectile 및 파생 (HomingProjectile·PiercingProjectile) component
부착 GameObject 전수 destroy
- 박스 시각화 name 5종 (Hitbox_Debug·ProjectileHitbox_Debug·
LaserHitbox_Debug·MeleeHitbox_Debug·Range_Debug) destroy
- Resources.FindObjectsOfTypeAll + scene.IsValid filter
(asset prefab 제외)
- removed 카운트 Debug.Log
기존 HideFlags.DontSave (60e28e3) 정합 외 추가 보험:
- DontDestroyOnLoad 경로 (코드베이스 검색 0건 — 방어 코드)
- Scene 영구 저장 누락 케이스
- 메모리 잔존 (Editor crash 후 재시작 등)
검증 (Play 모드):
- A02·A05 발사 후 spawn 카운트 6
- CleanupStalePooledSpawns 직접 호출 + 1 frame 후 카운트 0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
작업 1 — 피격 이펙트 상위 sortingOrder:
- Projectile.OnTriggerEnter2D OnHitFx — Renderer.sortingOrder += 100
- LightningStrikeSpawner OnHitFx + ExtraHitFx — 동일
- MeleeAreaSpawner fxGo — 동일
- LaserSpawner fx — 동일
- Enemy SpriteRenderer 영역 위·뒤쪽 가림 회피
작업 2 — 적 추적 각도 하단 보정:
- ProjectileSpawner.Trigger TargetEnemyOnFire 영역 toEnemy.y -= 0.5
- 적 transform.position 영역 상단 영역·hitbox 영역 영역 영역 적중 정합
- A08 영역 영역 영역 영역 영역 영역 적 hitbox 영역 영역 영역 적중
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
작업 1 — 캐스팅 이펙트 제거:
- A08.asset OffsetDistance.x 1.5 → 0 (Player 위치 spawn)
- A08.asset CastFxPrefab null
작업 2 — 가장 가까운 적 방향 발사:
- ActiveSkillData.TargetEnemyOnFire (bool) 신규 필드
- ProjectileSpawner.Trigger — TargetEnemyOnFire=true 시 FindObjectsByType<EnemyController> 영역 nearest 검출·facing = (enemyPos - playerPos).normalized
- 적 0명 시 PlayerController.Facing fallback (기존 정합)
- A08.asset TargetEnemyOnFire=1
벽·발판 관통 X — Projectile.Update 영역 Layer 0·16 OverlapPoint 영역 영역 영역 정합 (변경 X).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
원인: SelfDestruct 영역 즉시 Destroy(gameObject) → ParticleSystem 영역 진행 영역 trail·glow particle 즉시 사라짐 → 발사 영역 영역 영역 매번 시각 cut → "뚝뚝 끊기는" 인식.
fix:
- _fadeOutStarted flag — 중복 호출 차단
- Collider2D·_debugBoxTransform disable — 판정 종료
- _speed = 0 — 이동 정지
- ParticleSystem.Stop(true, StopEmitting) — emission 정지·기존 particle 자연 fade
- Destroy(gameObject, 0.5f) — 0.5s 후 Destroy (기존 particle lifetime 영역 자연 fade 완료)
- FADE_START_RATIO 0.8 → 0.85 (sprite fadeout 영역 영역 영역·자연 영역 영역)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
원인: fx.transform.localScale *= HitFxScale 영역 적용·그러나 ParticleSystem.MainModule.scalingMode 영역 = Local·Shape 영역 영역 영역 root scale 영역 영역 X·ParticleSystem 영역 자체 size 영역 영역 영역 영역.
fix: 모든 fx spawn 영역 ParticleSystem foreach 영역 영역 ScalingMode = Hierarchy 설정 + Play(true) 동시. Hierarchy 영역 = parent Transform scale 영역 정합 적용.
전수 적용 (7 파일):
- Projectile.OnTriggerEnter2D — OnHitFx
- ProjectileSpawner.Trigger — CastFx + ProjectilePrefab
- MeleeAreaSpawner.Trigger — fxGo
- LightningStrikeSpawner — OnHitFx + ExtraHitFx
- LaserSpawner.Trigger — fx
- PoisonSwampSpawner — swampGo + Marker.Tick fx
- SpiritFireSpawner — shieldGo
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
작업 1 — 캐스팅 이펙트 끝 지점 영역 투사체 발사:
- A08.asset OffsetDistance.x: 0 → 1.5
- ProjectileSpawner.Trigger 영역 spawnPos = playerPos + facing × 1.5 영역 캐스팅 끝 지점
- (FX_PinkArrow_Shoot 캐스팅 길이 영역 1.5 unit 추정·PD 측정 후 미세 조정 가능)
작업 2 — Hit FX 발사 시 Player 위치 발생 회피:
- 원인 추정: spawn 위치 = Player 위치 + OffsetDistance·작업 1 이전 OffsetDistance=0 영역 Player 위치 spawn → Player 근접 Enemy 즉시 hit → OnHit FX = Enemy 위치 ≈ Player 위치 → "Player에게 발생" 인식
- 작업 1 영역 spawn 위치 영역 Player 영역 1.5 우측 이동 → 자동 정정
- Projectile.OnTriggerEnter2D 영역 spawn 직후 0.1초 grace period 추가 (Time.unscaledTime - _spawnTime < 0.1f 영역 return) — 즉시 hit 차단·OnHitFx Player 위치 표시 회피
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
원인: CastFx Instantiate 영역 = Quaternion.Euler(0, 0, data.FxRotation) (=0) 영역. FX_PinkArrow_Shoot sprite left 기본 → 시전 영역 sprite left 표시·Player right 발사 방향과 반대.
fix:
- ProjectileSpawner.Trigger CastFx — facing angle + ProjectileAngleOffset + FxRotation 적용 (Projectile 본체 동일 패턴)
- 진단 Debug.Log 2종 회수 ([ProjectileSpawner] card·CastFx spawned·[Projectile] OnHit) — fileID 정정 완료·root 원인 확정 후 revert
A08 영역 ProjectileAngleOffset=180 영역 정합 (sprite left → right) → CastFx·Projectile 동일 방향.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
본 PM 자성 #16 영역 fileID 측정 영역 잘못된 방법 영역 영역 = A06·A12 .asset 영역 동일 문제 일괄 정정.
정정:
- A06 OnDotFx fileID 1856636965874036819 → 3507146902299718551 (FX_Venom_Spray root)
- A12 OnHitFx fileID 215796562487493921 → 5983634136545354204 (FX_Icelight_Seal root)
정합 (변경 X):
- A06 OnHitFx fileID 113285305800631535 (FX_Venom_Swamp root·정합·우연)
- A11 OnHitFx fileID 1589202452151042601 (FX_Rotating shield root·정합)
- A_Laser·A02·A04·A13 영역 = PD 영역 직접 Inspector 영역 영역 영역 (본 PM 영역 직접 작성 X·영역 영역)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
본 PM 자성 #16 (헌법급) — fileID 측정 영역 잘못된 방법 사용.
원인: 본 PM 직전 commit 5077f5d 영역 grep -m 1 "^--- !u!1 &" 영역 사용·**첫 GameObject** fileID 측정 → Unity prefab 영역 root GameObject 영역 X (자식 GameObject 영역).
PD Inspector 측정 결과:
- OnHitFx: "Fragments" (FX_PinkMagicArrow_Hit prefab 영역 자식 GameObject) → root 영역 정정
- CastFx: "sheet" (FX_PinkArrow_Shoot prefab 영역 자식 GameObject) → root 영역 정정
정정:
- OnHitFxPrefab fileID 1108032389789601088 → 7053558978182834975 (FX_PinkMagicArrow_Hit root)
- CastFxPrefab fileID 1571108645336829551 → 9207792929607053519 (FX_PinkArrow_Shoot root)
올바른 root fileID 측정 방법: awk 영역 m_Name == prefab name + m_Father=0 정합 GameObject ID.
재발 방지: prefab fileID 측정 시 첫 GameObject 영역 가정 X·반드시 m_Name + m_Father=0 정합 root 영역 확정.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
원인: 직전 aa6cef1 영역 Debug.Log interpolated string 영역 `\"NULL\"` escape 사용·C# interpolated string escape 미지원 → 컴파일 에러.
fix: ternary 결과 영역 변수 분리 (castName·projName·hitName).
본 PM 자성 #15 — Edit 후 컴파일 사전 검증 누락. Unity Editor 영역 컴파일 영역 영역 영역 본 PM 영역 X 영역 영역 = PD 영역 보고 후 영역. C# string escape 영역 사전 측정 의무.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A08.asset 영역 ProjectilePrefab·OnHitFxPrefab·CastFxPrefab GUID 정합 측정 정합·코드 정합. 그러나 PD 영역 시전·피격 X 보고 → 실측 진단 필요.
진단 Log 2종 (회수 의무·PD Console 측정 후 본 PM revert):
- ProjectileSpawner.Trigger — [ProjectileSpawner] card·CastFx·ProjPrefab·OnHitFx 매핑 측정·CastFx spawn 확인
- Projectile.OnHit — [Projectile] OnHit card·OnHitFx spawn name·pos 확인
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>