EerieVillage/Assets/Scripts/Skills/Effectors/Projectile.cs

299 lines
14 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using UnityEngine;
using Platformer.Mechanics;
using Platformer.Gameplay;
using static Platformer.Core.Simulation;
namespace EerieVillage.Skills.Effectors
{
/// <summary>
/// 투사체 기본 컴포넌트. Line 궤적 직선 이동·단일 적 타격 후 소멸.
/// BT12-Dev Phase 2-B §4-2.
/// 파생: <see cref="HomingProjectile"/> (A15 추적 화염구).
/// </summary>
public class Projectile : MonoBehaviour
{
protected ActiveSkillData _data;
protected ActiveSkillRuntime _runtime;
protected PlayerSkillInventory _inventory;
protected Vector2 _direction;
protected float _speed = 6f; // BT12-Dev 2026-05-10 PD — 거리 차이 체감 영역 영역 (12 → 6)
protected float _lifetime = 5f; // 영역 영역 영역 (Long 18.67 / 6 = 3.11s 영역 영역)
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// BT12-Dev 2026-05-10 (PD #1·#2) — 거리 제한·벽 충돌 영역
protected Vector2 _spawnPosition;
protected float _maxRange;
protected float _spawnTime;
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// 동일 투사체로 동일 Collider 중복 타격 방지
protected readonly HashSet<Collider2D> _hitTargets = new HashSet<Collider2D>();
// BT12-Dev 2026-05-13 — 페이드아웃·축소 (PD 지시: 사거리 80%~100% 영역 alpha 0·scale 추가 50% 축소)
protected Vector3 _baseScale; // 페이드 보간 기준 (= _originalScale × ProjectileFxScale·매 frame 갱신)
protected Vector3 _originalScale; // PD 정합 2026-05-13 — Inspector ProjFxScale 변경 영역 매 frame 영역 영역 base
protected Renderer[] _renderers;
protected MaterialPropertyBlock _mpb;
protected float[] _baseAlphas;
const float FADE_START_RATIO = 0.8f;
/// <summary>
/// ProjectileSpawner.Trigger 에서 Instantiate 직후 호출.
/// </summary>
public virtual void Initialize(ActiveSkillRuntime runtime, PlayerSkillInventory inventory, Vector2 direction)
{
_runtime = runtime;
_data = runtime.ActiveData;
_inventory = inventory;
_direction = direction.normalized;
_hitTargets.Clear();
2026-05-13 08:27:49 +00:00
// PD 지시 2026-05-13 — 투사체 root = 박스(판정) 정합. FxRotation 미적용 (시각 전용·박스 회전 금지).
float angle = Mathf.Atan2(_direction.y, _direction.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, angle);
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// BT12-Dev 2026-05-10 (PD #1) — 거리 제한 영역 영역 spawn 위치 저장
_spawnPosition = transform.position;
_spawnTime = Time.time;
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// PD 지시 2026-05-13 — 투사체 사정거리·속도 Inspector 직접 조절 (RangeTier·camWidth·mults 계산 폐기)
_maxRange = (_data.MaxRange > 0.01f) ? _data.MaxRange : 10f;
_speed = (_data.ProjectileSpeed > 0.01f) ? _data.ProjectileSpeed : 6f;
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// PD 정합 2026-05-13 — Inspector ProjFxScale 매 frame 영역 영역 _originalScale 저장
_originalScale = transform.localScale;
transform.localScale *= _data.ProjectileFxScale;
_baseScale = transform.localScale;
// PD 지시 2026-05-13 — 판정 영역 시각화 (자체 Collider2D bounds 영역 자식 박스·이동·페이드 정합)
SpawnHitboxDebugChild();
// PD 지시 2026-05-13 — 투사체 사거리 파란 박스 시각화 (발사 후 3초 유지)
HitboxDebug.SpawnRange(_spawnPosition, _direction, _maxRange, 3f);
// Renderer·MaterialPropertyBlock 캐싱 + 기본 alpha 저장
_renderers = GetComponentsInChildren<Renderer>();
_mpb = new MaterialPropertyBlock();
_baseAlphas = new float[_renderers.Length];
for (int i = 0; i < _renderers.Length; i++)
{
var r = _renderers[i];
if (r.sharedMaterial != null && r.sharedMaterial.HasProperty("_TintColor"))
_baseAlphas[i] = r.sharedMaterial.GetColor("_TintColor").a;
else if (r.sharedMaterial != null && r.sharedMaterial.HasProperty("_Color"))
_baseAlphas[i] = r.sharedMaterial.GetColor("_Color").a;
else _baseAlphas[i] = 1f;
}
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// Phase 2-B: 풀링 미도입 — Invoke 기반 자동 소멸 (거리 제한 영역 영역 영역 영역 영역 안전망)
Invoke(nameof(SelfDestruct), _lifetime);
}
// BT12-Dev 2026-05-13 — 사거리 80~100% 영역 scale·alpha 보간 (PD 지시)
// ratio < 0.8 : scale=1.0배 (시작 50% 그대로)·alpha 그대로
// ratio 0.8~1.0 : t=(ratio-0.8)/0.2 → scale = base × (1 - 0.5t)·alpha = base × (1 - t)
protected void ApplyFadeoutByRange(float ratio)
{
if (_renderers == null) return;
float t = Mathf.Clamp01((ratio - FADE_START_RATIO) / (1f - FADE_START_RATIO));
float scaleMul = 1f - 0.5f * t;
float alphaMul = 1f - t;
transform.localScale = _baseScale * scaleMul;
for (int i = 0; i < _renderers.Length; i++)
{
var r = _renderers[i];
if (r == null) continue;
r.GetPropertyBlock(_mpb);
string propName = (r.sharedMaterial != null && r.sharedMaterial.HasProperty("_TintColor"))
? "_TintColor"
: "_Color";
Color baseCol = (r.sharedMaterial != null && r.sharedMaterial.HasProperty(propName))
? r.sharedMaterial.GetColor(propName)
: Color.white;
baseCol.a = _baseAlphas[i] * alphaMul;
_mpb.SetColor(propName, baseCol);
r.SetPropertyBlock(_mpb);
}
}
// BT12-Dev 2026-05-10 회귀 정정 — Wall Layer 실측 (Player Layer=13·Enemy Layer=14·Level Tilemap Layer=0).
// Layer 0 (Default) Solid Collider: Level TilemapCollider2D + GameObject·Alien BoxCollider2D — Wall 정합.
// Trigger collider (CinemachineConfiner Polygon·Token·DeathZone Box) = useTriggers=false 영역 자동 제외.
// Player·Enemy 영역 Layer 0 외 영역 → OverlapPoint hit 무관.
protected static readonly int WallLayerMask = (1 << 0);
protected virtual void Update()
{
// PD 지시 2026-05-13 — Inspector HitboxSize 변경 즉시 반영
SyncHitboxToData();
transform.position += (Vector3)(_direction * _speed * Time.deltaTime);
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// BT12-Dev 2026-05-10 (PD #1) — 거리 제한 영역 영역 SelfDestruct
float dist = Vector2.Distance(transform.position, _spawnPosition);
if (dist >= _maxRange)
{
SelfDestruct();
return;
}
// BT12-Dev 2026-05-13 — 사거리 80~100% 영역 페이드아웃·축소 (PD 지시)
if (_maxRange > 0.01f)
{
ApplyFadeoutByRange(dist / _maxRange);
}
// BT12-Dev 2026-05-10 (PD #2 fix·재발 정정 #2) — Wall OverlapPoint·useTriggers=false (CinemachineConfiner Trigger 영역 영역 영역).
// grace period 0.05s 영역 spawn 시점 즉시 SelfDestruct 회피.
if (Time.time - _spawnTime > 0.05f)
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
{
var filter = new ContactFilter2D();
filter.useTriggers = false; // Trigger collider (CinemachineConfiner 영역) 영역 영역
filter.useLayerMask = true;
filter.layerMask = WallLayerMask;
var results = new Collider2D[1];
int hitCount = Physics2D.OverlapPoint(transform.position, filter, results);
if (hitCount > 0)
{
SelfDestruct();
}
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
}
}
protected virtual void OnTriggerEnter2D(Collider2D other)
{
fix(BT12-Dev): EnemyDeath 근본 fix — Animator transition 5 + UnscaledTime + 진단 회수 근본 원인 (본 PM MCP 직접 진단): - Enemy.controller 영역 Idle/Run/Hurt → Death/Hurt transition 부재 → death Trigger 호출 영역 transition X - Animator updateMode = Normal·Time.timeScale = 0 (LevelUp 카드 선택) → Animator.Update 정지 → transition 영역 X 해결 (본 PM 자율 결정 + MCP 직접 적용): - Enemy.controller transition 5 추가 (Idle→Death, Idle→Hurt, Run→Death, Run→Hurt, Hurt→Death) → manage_animation controller_add_transition 영역 직접 호출 - EnemyDeath.cs animator.updateMode = AnimatorUpdateMode.UnscaledTime 추가 → Time.timeScale = 0 영역 영역 Animator 영역 정상 진행 → death animation 재생 + transition 발동 - 진단 Debug.Log 회수: Projectile (8 분기)·AttackHitbox (1줄)·EnemyDeath (1줄) → 사망 원인 확정 영역 회수 의무 정합 본 PM MCP 직접 진단 절차: 1. read_console — Console 직접 읽기 (Health@Enemy·Projectile 출력 검증) 2. controller_get_info — Enemy.controller parameters·states·transitions 직접 검증 3. execute_code — Player·Enemy 위치·Schedule<EnemyDeath> 직접 호출·Animator state 검증 4. manage_animation controller_add_transition — Animator transition 5 직접 추가 5. anim.SetTrigger("death") + anim.Update(0.5f) → Baddie-Death 진입 정합 검증 PD 결정 (2026-05-10): "MCP 활용해서 네가 직접 체크해" — 본 PM 자율 진단·fix·검증. PD 자성 #13: PD에게 작업 떠넘기기 금지·MCP 능동 활용 의무.
2026-05-09 16:09:17 +00:00
if (_hitTargets.Contains(other)) return;
// PD 지시 2026-05-13 — 투사체끼리 충돌 X·통과 정합 (Projectile 컴포넌트 동족 skip·Wall 판정 이전)
if (other.GetComponent<Projectile>() != null) return;
// PD 지시 2026-05-09 후속 방어 — 자기(Player) hit·자기 자신·hit 방어.
fix(BT12-Dev): EnemyDeath 근본 fix — Animator transition 5 + UnscaledTime + 진단 회수 근본 원인 (본 PM MCP 직접 진단): - Enemy.controller 영역 Idle/Run/Hurt → Death/Hurt transition 부재 → death Trigger 호출 영역 transition X - Animator updateMode = Normal·Time.timeScale = 0 (LevelUp 카드 선택) → Animator.Update 정지 → transition 영역 X 해결 (본 PM 자율 결정 + MCP 직접 적용): - Enemy.controller transition 5 추가 (Idle→Death, Idle→Hurt, Run→Death, Run→Hurt, Hurt→Death) → manage_animation controller_add_transition 영역 직접 호출 - EnemyDeath.cs animator.updateMode = AnimatorUpdateMode.UnscaledTime 추가 → Time.timeScale = 0 영역 영역 Animator 영역 정상 진행 → death animation 재생 + transition 발동 - 진단 Debug.Log 회수: Projectile (8 분기)·AttackHitbox (1줄)·EnemyDeath (1줄) → 사망 원인 확정 영역 회수 의무 정합 본 PM MCP 직접 진단 절차: 1. read_console — Console 직접 읽기 (Health@Enemy·Projectile 출력 검증) 2. controller_get_info — Enemy.controller parameters·states·transitions 직접 검증 3. execute_code — Player·Enemy 위치·Schedule<EnemyDeath> 직접 호출·Animator state 검증 4. manage_animation controller_add_transition — Animator transition 5 직접 추가 5. anim.SetTrigger("death") + anim.Update(0.5f) → Baddie-Death 진입 정합 검증 PD 결정 (2026-05-10): "MCP 활용해서 네가 직접 체크해" — 본 PM 자율 진단·fix·검증. PD 자성 #13: PD에게 작업 떠넘기기 금지·MCP 능동 활용 의무.
2026-05-09 16:09:17 +00:00
if (other.GetComponent<PlayerController>() != null) return;
feat(BT12-Dev Phase 2-D): BT12-MVP-A 통합 정정 (placeholder → 정식 ActiveSkillData) + Phase 2-B .meta 보충 C49 Phase 2-D — Sonnet 위임 (코드 Write·검증만·git 본 PM 처리 정합·feedback_pm_sonnet_subagent_unauthorized_push 정합). 수정 6 파일: - LevelUpManager.cs (Phase 2-D 정정·_pool 제거·SkillRuntimeFactory.RandomDraw3·HandleCardConfirmed(ActiveSkillData)·PlayerSkillInventory.AddSkillByCardId) - SkillSelectionUI.cs (Show(List<ActiveSkillData>)·_selected·BindSlot·OnCardSelected ActiveSkillData 전환) - SkillCardSlot.cs (Bind(ActiveSkillData)·DisplayName/Description/Icon PascalCase·rarity 배너 갈색 고정) - PlayerController.cs (PlayerSkillInventory 자동 부착·line 100) - Projectile.cs (Layer Enemy 미등재 fallback — EnemyController 컴포넌트 검사·proxy) - SkillRuntimeFactory.cs (RandomDraw3 메서드·Active 카테고리 무작위 3장) 신규 9 .meta (Phase 2-B Sonnet 자율 push 영역 영역 영역 영역 X·Unity Editor Refresh 후 자동 생성·본 commit 보충): - Skills.meta + Effectors.meta + 7 Effectors/*.cs.meta Layer Enemy 영역 = proxy 개선 신호 (C2-2): - 현 시점 = Projectile.OnTriggerEnter2D 영역 EnemyController 컴포넌트 fallback (proxy) - 근본 해결안 = Layer "Enemy" 정식 등재 (별도 PD 안건·후속) 기능: - 적 처치 → EXP +1 → 즉시 레벨업 → 카드 3장 노출 → 선택 → PlayerSkillInventory 등록 → ActiveSkillRuntime Tick → 1.5s 영역 자동 발사 + 부가 효과 (DoT·Stun·Slow·DebuffStack) 기존 영역 변경 X (BT5-Dev·BT7-Dev·Phase 2-A·2-B·2-C·BT12-MVP-A asset 5장·Scene·SkillCardPlaceholder·SkillCardPlaceholderPool·deprecate 차후) Compile error 0건 (read_console·도메인 리로드 정합) C49 — Phase 2-D Sonnet 위임 + Phase 3 본 PM 직접 (단순 반복 카탈로그 v1) C50 — ~95K (PD 사전 승인 70~95K 영역 상한 정합) C19-2 — Sonnet 자율 git X·본 PM 직접 commit·push (feedback 정합) pm-auditor 사전 감사 = Pass + Minor 1 (Layer fallback proxy 명시·본 commit + 대화로그 영역 정정 적용) 후속: - Phase 2-A·2-B·2-C·2-D 영역 PD Play 검증 (자동 발동·레벨업·카드 선택·등록·Tick) - Layer "Enemy" 정식 등재 (별도 PD 안건·근본 해결안) - Phase 2-E EditMode 테스트 - 다른 카테고리 (B·C·D·E·F) 영역 - BT12-MVP-A asset 5장 deprecate (차기) - Screenshots·_Recovery .gitignore (별도)
2026-05-09 11:57:28 +00:00
// Enemy 레이어 한정.
int enemyLayer = LayerMask.NameToLayer("Enemy");
fix(BT12-Dev): EnemyDeath 근본 fix — Animator transition 5 + UnscaledTime + 진단 회수 근본 원인 (본 PM MCP 직접 진단): - Enemy.controller 영역 Idle/Run/Hurt → Death/Hurt transition 부재 → death Trigger 호출 영역 transition X - Animator updateMode = Normal·Time.timeScale = 0 (LevelUp 카드 선택) → Animator.Update 정지 → transition 영역 X 해결 (본 PM 자율 결정 + MCP 직접 적용): - Enemy.controller transition 5 추가 (Idle→Death, Idle→Hurt, Run→Death, Run→Hurt, Hurt→Death) → manage_animation controller_add_transition 영역 직접 호출 - EnemyDeath.cs animator.updateMode = AnimatorUpdateMode.UnscaledTime 추가 → Time.timeScale = 0 영역 영역 Animator 영역 정상 진행 → death animation 재생 + transition 발동 - 진단 Debug.Log 회수: Projectile (8 분기)·AttackHitbox (1줄)·EnemyDeath (1줄) → 사망 원인 확정 영역 회수 의무 정합 본 PM MCP 직접 진단 절차: 1. read_console — Console 직접 읽기 (Health@Enemy·Projectile 출력 검증) 2. controller_get_info — Enemy.controller parameters·states·transitions 직접 검증 3. execute_code — Player·Enemy 위치·Schedule<EnemyDeath> 직접 호출·Animator state 검증 4. manage_animation controller_add_transition — Animator transition 5 직접 추가 5. anim.SetTrigger("death") + anim.Update(0.5f) → Baddie-Death 진입 정합 검증 PD 결정 (2026-05-10): "MCP 활용해서 네가 직접 체크해" — 본 PM 자율 진단·fix·검증. PD 자성 #13: PD에게 작업 떠넘기기 금지·MCP 능동 활용 의무.
2026-05-09 16:09:17 +00:00
bool isEnemy = (enemyLayer != -1 && other.gameObject.layer == enemyLayer)
|| other.GetComponent<EnemyController>() != null;
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
if (isEnemy)
{
var health = other.GetComponent<Health>();
// PD 지시 2026-05-13 — 죽은 Enemy 와 충돌 시도해도 Projectile 영역 SelfDestruct (영역 영역 통과 회피)
if (health == null || !health.IsAlive) { SelfDestruct(); return; }
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
_hitTargets.Add(other);
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// 유효 대미지 산출 — BT12-Dev 2026-05-10 임시 (PD 지시): 기본 공격력 5 하한 강제.
int damage = Mathf.Max(_runtime.CalculateEffectiveDamage(), 5);
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// 피해 적용
health.Decrement(damage);
// PD 지시 2026-05-13 — 피격 이펙트 spawn·HitFxScale·FxRotation 적용
if (_data != null && _data.OnHitFxPrefab != null)
{
var fx = Object.Instantiate(_data.OnHitFxPrefab, other.transform.position, Quaternion.Euler(0f, 0f, _data.FxRotation));
fx.hideFlags = HideFlags.DontSave; // PD 지시 2026-05-13 — Scene 저장 회피
fx.transform.localScale *= _data.HitFxScale;
AutoDestroyOnParticleEnd(fx);
}
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// 부가 효과 (DoT·Stun·Slow·DebuffStack) — StatusApplier 위임
var enemy = other.GetComponent<EnemyController>();
if (enemy != null)
{
StatusApplier.Apply(_data, enemy);
}
// Enemy 즉사 시 EnemyDeath 체인 발동
if (!health.IsAlive && enemy != null)
{
Schedule<EnemyDeath>().enemy = enemy;
}
// 단일 적 타격 후 소멸 (관통 미지원 — Phase 2 범위 내)
SelfDestruct();
return;
}
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
// BT12-Dev 2026-05-10 (PD #2) — 벽 충돌 시 SelfDestruct.
// Layer 0 (Default·Ground) · Layer 16 (Foreground·발판) 영역 영역 Tilemap·Composite·Box collider 영역 정합.
// 레이저 영역 영역 영역 영역 영역 X — 본 Projectile 영역 영역 (영역 영역 영역 영역 X) — 모든 Projectile 영역 SelfDestruct.
int otherLayer = other.gameObject.layer;
bool isWall = (otherLayer == 0 || otherLayer == 16);
if (isWall)
{
feat(BT12-Dev): PD 4 지시 — Projectile 거리 제한·벽 충돌·특성 가시화·Icon UI 매핑 (MCP 자율) PD 지시 (2026-05-10): 1. 투사체 종류 영역 일정 거리 영역 소멸 (Camera width × 1.5) 2. 레이저 외 투사체 영역 벽 충돌 시 소멸 3. 스킬 특성 영역 컨셉 동작 4. 스킬 선택 UI 영역 아이콘 노출 본 PM MCP 자율 진행: ==== PD #1: 거리 제한 ==== Projectile.Initialize: - _spawnPosition 저장 - _maxRange = Camera.orthographicSize × 2 × aspect × 1.5 (가로 × 1.5) Projectile.Update: - Distance(transform.position, _spawnPosition) >= _maxRange → SelfDestruct ==== PD #2: 벽 충돌 ==== Projectile.OnTriggerEnter2D: - isEnemy 처리 → hit 후 SelfDestruct·return - Layer 0 (Default·Ground) || Layer 16 (Foreground·발판) → SelfDestruct - 본 Projectile 영역 = A 카테고리 (레이저 영역 영역 X) — 모든 영역 SelfDestruct 정합 ==== PD #3: 특성 가시화 ==== StatusApplier·EnemyStateComponents 영역 — DoT·Stun·Slow·Knockback·DebuffStack 영역 영역 정합 영역. 근본 영역 — Enemy hp 4·damage 5·1hit 즉사 → 효과 시각 X. 정정 — Enemy.prefab maxHearts 1→5 (maxHP 4→20) — A02 DoT·A03 Stun·A14 Slow 영역 4 hit 영역 영역 영역. ==== PD #4: Icon UI ==== SkillCardSlot _icon 매핑 X 영역 — BannerFrame04_Divided 자식 영역 SkillIcon GameObject 신규 추가 + Image 컴포넌트 - anchorMin·max (0.5, 0.7)·sizeDelta (120, 120)·preserveAspect true - 3 슬롯 영역 _icon 필드 매핑 정합 Scene SkillSelectionCanvas·Enemy 인스턴스 RevertPrefabInstance — prefab 변경 동기화 MCP Play 검증: - enemyMaxHP 20 ✅·컴파일 에러 0 ✅·Icon 매핑 3/3 ✅
2026-05-10 07:23:34 +00:00
SelfDestruct();
}
}
protected void SelfDestruct()
{
CancelInvoke(nameof(SelfDestruct));
Destroy(gameObject);
}
// PD 지시 2026-05-13 — 시각화 박스 자식 reference (Update 영역 매 frame Inspector 정합 갱신용)
protected Transform _debugBoxTransform;
// PD 지시 2026-05-13 — Projectile 자체 Collider2D bounds 영역 자식 박스 부착 (이동·페이드 정합·HitboxSize 정합)
void SpawnHitboxDebugChild()
{
var col = GetComponent<Collider2D>();
if (col == null) return;
Vector2 size = (col is BoxCollider2D box) ? box.size : new Vector2(col.bounds.size.x / Mathf.Max(0.01f, Mathf.Abs(transform.lossyScale.x)),
col.bounds.size.y / Mathf.Max(0.01f, Mathf.Abs(transform.lossyScale.y)));
Vector2 offset = (col is BoxCollider2D box2) ? box2.offset : (col is CircleCollider2D cc ? cc.offset : Vector2.zero);
var go = new GameObject("ProjectileHitbox_Debug");
// PD 지시 2026-05-13 — 런타임 spawn 박스 Scene 저장 회피
go.hideFlags = HideFlags.DontSave;
go.transform.SetParent(transform, false);
go.transform.localPosition = new Vector3(offset.x, offset.y, 0f);
go.transform.localScale = new Vector3(size.x, size.y, 1f);
var sr = go.AddComponent<SpriteRenderer>();
sr.sprite = HitboxDebug.GetWhiteSprite();
sr.color = new Color(1f, 0f, 0f, 0.35f);
sr.sortingOrder = 100;
sr.enabled = HitboxDebug.ShowDebugVisuals;
_debugBoxTransform = go.transform;
}
// PD 지시 2026-05-13 — Inspector 영역 HitboxSize·ProjFxScale 변경 시 발사 중인 Projectile 도 즉시 반영.
protected void SyncHitboxToData()
{
if (_data == null) return;
// HitboxSize 영역 BoxCollider2D + 자식 박스 정합
var box = GetComponent<BoxCollider2D>();
if (box != null && box.size != _data.HitboxSize)
{
box.size = _data.HitboxSize;
}
if (_debugBoxTransform != null)
{
var s = _debugBoxTransform.localScale;
if (Mathf.Abs(s.x - _data.HitboxSize.x) > 0.001f || Mathf.Abs(s.y - _data.HitboxSize.y) > 0.001f)
{
_debugBoxTransform.localScale = new Vector3(_data.HitboxSize.x, _data.HitboxSize.y, 1f);
}
}
// PD 정합 — ProjectileFxScale 영역 _baseScale 영역 매 frame 영역 (Inspector 변경 영역 즉시)
_baseScale = _originalScale * _data.ProjectileFxScale;
}
// BT12-Dev 2026-05-13 — ParticleSystem 영역 자동 destroy. main.duration + startLifetime.constantMax 영역 영역 후 Destroy.
protected static void AutoDestroyOnParticleEnd(GameObject fxGo)
{
if (fxGo == null) return;
var ps = fxGo.GetComponent<ParticleSystem>();
if (ps == null) ps = fxGo.GetComponentInChildren<ParticleSystem>();
float lifetime = 3f; // fallback
if (ps != null)
{
var main = ps.main;
lifetime = main.duration + main.startLifetime.constantMax + 0.2f;
}
Object.Destroy(fxGo, lifetime);
}
}
}