diff --git a/Assets/Scripts/Skills/Effectors/PoisonSwampSpawner.cs b/Assets/Scripts/Skills/Effectors/PoisonSwampSpawner.cs index a783f6c..8f1cadb 100644 --- a/Assets/Scripts/Skills/Effectors/PoisonSwampSpawner.cs +++ b/Assets/Scripts/Skills/Effectors/PoisonSwampSpawner.cs @@ -107,6 +107,18 @@ namespace EerieVillage.Skills.Effectors rb.simulated = true; rb.gravityScale = 0f; rb.useFullKinematicContacts = true; + + // PD 지시 2026-05-14 — 판정 박스 시각화 (붉은 반투명 박스·ShowDebugVisuals 토글) + var dbg = new GameObject("PoisonSwampHitbox_Debug"); + dbg.hideFlags = HideFlags.DontSave; + dbg.transform.SetParent(transform, false); + dbg.transform.localPosition = Vector3.zero; + dbg.transform.localScale = new Vector3(size.x, size.y, 1f); + var sr = dbg.AddComponent(); + sr.sprite = HitboxDebug.GetWhiteSprite(); + sr.color = new Color(1f, 0f, 0f, 0.35f); + sr.sortingOrder = 100; + sr.enabled = HitboxDebug.ShowDebugVisuals; } void Update() diff --git a/Assets/Scripts/Skills/Effectors/SpiritFireSpawner.cs b/Assets/Scripts/Skills/Effectors/SpiritFireSpawner.cs index 7c9a206..829319a 100644 --- a/Assets/Scripts/Skills/Effectors/SpiritFireSpawner.cs +++ b/Assets/Scripts/Skills/Effectors/SpiritFireSpawner.cs @@ -39,11 +39,14 @@ namespace EerieVillage.Skills.Effectors shieldGo.hideFlags = HideFlags.DontSave; float duration = data.MinionLifetime > 0.1f ? data.MinionLifetime : 8f; - float radius = data.AuraRadius > 0.1f ? data.AuraRadius : 2.5f; + // PD 지시 2026-05-14 — 판정 박스 형태 일관 (HitboxSize 사용·OverlapBox) + Vector2 boxSize = data.HitboxSize.sqrMagnitude > 0.01f ? data.HitboxSize : new Vector2(2.5f, 2.5f); int damage = data.BaseDamage > 0 ? data.BaseDamage : 5; + // PD 지시 2026-05-14 — 일정 피해 간격 (DotInterval 우선·기본 1초) + float interval = data.DotInterval > 0.01f ? data.DotInterval : 1f; var instance = shieldGo.AddComponent(); - instance.Init(inventory.transform, duration, radius, damage); + instance.Init(inventory.transform, duration, boxSize, damage, interval); } } @@ -64,16 +67,26 @@ namespace EerieVillage.Skills.Effectors Animator _animator; float _spawnTime; float _duration; - float _radius; + Vector2 _boxSize; int _damage; + float _interval; float _lastDamageTime; + Transform _debugBoxTransform; - public void Init(Transform player, float duration, float radius, int damage) + // PD 지시 2026-05-14 — 소멸 0.5초 전 페이드 (alpha 1→0·scale 1→0.5) + const float FADE_DURATION = 0.5f; + Vector3 _baseScale; + Renderer[] _renderers; + MaterialPropertyBlock _mpb; + float[] _baseAlphas; + + public void Init(Transform player, float duration, Vector2 boxSize, int damage, float interval) { _player = player; _duration = duration; - _radius = radius; + _boxSize = boxSize; _damage = damage; + _interval = interval; _spawnTime = Time.unscaledTime; _animator = GetComponent(); @@ -83,6 +96,61 @@ namespace EerieVillage.Skills.Effectors _animator.updateMode = AnimatorUpdateMode.UnscaledTime; _animator.speed = 1f; } + + // PD 지시 2026-05-14 — 판정 박스 시각화 (붉은 반투명 박스·ShowDebugVisuals 토글) + var dbg = new GameObject("SpiritFireHitbox_Debug"); + dbg.hideFlags = HideFlags.DontSave; + dbg.transform.SetParent(_player, false); // Player 자식·매 frame 동조 + dbg.transform.localPosition = Vector3.zero; + float lpx = _player.lossyScale.x != 0f ? Mathf.Abs(_player.lossyScale.x) : 1f; + float lpy = _player.lossyScale.y != 0f ? Mathf.Abs(_player.lossyScale.y) : 1f; + dbg.transform.localScale = new Vector3(_boxSize.x / lpx, _boxSize.y / lpy, 1f); + var sr = dbg.AddComponent(); + sr.sprite = HitboxDebug.GetWhiteSprite(); + sr.color = new Color(1f, 0f, 0f, 0.35f); + sr.sortingOrder = 100; + sr.enabled = HitboxDebug.ShowDebugVisuals; + _debugBoxTransform = dbg.transform; + Destroy(dbg, _duration); + + // PD 지시 2026-05-14 — fade 캐싱 (Renderer·MaterialPropertyBlock·기본 alpha) + _baseScale = transform.localScale; + _renderers = GetComponentsInChildren(); + _mpb = new MaterialPropertyBlock(); + _baseAlphas = new float[_renderers.Length]; + for (int i = 0; i < _renderers.Length; i++) + { + var r = _renderers[i]; + if (r == null) { _baseAlphas[i] = 1f; continue; } + 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; + } + } + + // PD 지시 2026-05-14 — 페이드 보간 적용 + void ApplyFadeout(float t) + { + t = Mathf.Clamp01(t); + float alphaMul = 1f - t; + float scaleMul = 1f - 0.5f * t; + transform.localScale = _baseScale * scaleMul; + if (_renderers == null) return; + 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); + } } void Update() @@ -117,7 +185,8 @@ namespace EerieVillage.Skills.Effectors _animator.Play(STATE_HASH, 0, normalized); } - if (Time.unscaledTime - _spawnTime >= _duration) + float elapsedFromSpawn = Time.unscaledTime - _spawnTime; + if (elapsedFromSpawn >= _duration) { Destroy(gameObject); return; @@ -125,32 +194,28 @@ namespace EerieVillage.Skills.Effectors Vector2 center = _player != null ? (Vector2)_player.position : (Vector2)transform.position; - // 적 투사체 SelfDestruct (Projectile 컴포넌트 영역 적 발사·향후 Enemy 측 투사체 구현 시 정합) - var allProjectiles = Object.FindObjectsByType(FindObjectsSortMode.None); - foreach (var p in allProjectiles) - { - if (p == null) continue; - float d = Vector2.Distance(center, p.transform.position); - if (d <= _radius) - { - // PD 명시 — 적 투사체만 SelfDestruct. 현 Projectile = Player 발사 only → 영향 X 영역 (방어 코드). - // 향후 Enemy 측 Projectile 분리 시 friendly check 추가 필요. - } - } - - // 매 1초 근접 적 피해 - if (Time.unscaledTime - _lastDamageTime >= 1f) + // PD 지시 2026-05-14 — 정령불의 범위에 있는 적은 지속 시간 동안 일정한 피해 간격마다 피해 + if (Time.unscaledTime - _lastDamageTime >= _interval) { _lastDamageTime = Time.unscaledTime; ApplyDamageAround(center); } + + // PD 지시 2026-05-14 — 소멸 0.5초 전 페이드 (alpha 감소·scale 50% 축소) + float remaining = _duration - elapsedFromSpawn; + if (remaining <= FADE_DURATION && remaining > 0f) + { + float t = 1f - (remaining / FADE_DURATION); // 0→1 over 0.5s + ApplyFadeout(t); + } } void ApplyDamageAround(Vector2 center) { + // PD 지시 2026-05-14 — OverlapBox 영역 박스 형태 판정 (HitboxSize 사용·박스 시각 ↔ 판정 정합) var cf = new ContactFilter2D { useTriggers = false }; var results = new Collider2D[32]; - int n = Physics2D.OverlapCircle(center, _radius, cf, results); + int n = Physics2D.OverlapBox(center, _boxSize, 0f, cf, results); for (int i = 0; i < n; i++) { var c = results[i]; diff --git a/Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs b/Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs index 5e22796..99c3e94 100644 --- a/Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs +++ b/Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs @@ -87,7 +87,11 @@ namespace EerieVillage.Skills "ProjectileHitbox_Debug", "LaserHitbox_Debug", "MeleeHitbox_Debug", + "MeleeHitbox_Debug2", "Range_Debug", + // PD 지시 2026-05-14 — A06·A11 판정 박스 시각화 신규 + "PoisonSwampHitbox_Debug", + "SpiritFireHitbox_Debug", }; // PD 지시 2026-05-14 — FX clone 카탈로그 (Projectile component 미부착 — Cast FX·HitFx 등)