// ───────────────────────────────────────────────────────────────────────────── // WLActorScale.cs — 몹 「쉬는 크기」 기준 하나 (#918 · 2026-10-17) // // PD 원문: 「방패치기 및 검 궁극기 등을 사용할 때 적의 크기가 자꾸 커지는데 확인해보고 수정해줘」 // ■ 원인(코드 확인) — 잠깐 크기를 바꾸는 효과 둘이 저마다 「지금 크기」를 기준으로 잡았다: // · 피격 스케일 펀치(WLHitFeelRunner.CoScalePunch · 맞을 때 커졌다 돌아옴) // · 공격 예고 부풀기(Telegraph · 공격 직전 커짐) // 연타(다단 히트 0.1 초 간격)로 펀치가 겹치면 새 펀치가 앞 펀치로 커진 크기를 기준으로 잡아 그 크기로 되돌리고, // 앞 펀치는 「남이 바꿨다」고 보고 복원을 포기 → 칠 때마다 조금씩 커졌다(예고 부풀기와 겹쳐도 같다). // ■ 처리 — 효과가 시작할 때 Begin(진행 중인 효과가 없을 때만 지금 크기를 쉬는 크기로 기억 · 있으면 그 기억을 그대로) · // 효과는 쉬는 크기 × 배율만 쓴다 · End 에서 마지막 효과가 끝나면 쉬는 크기로 되돌린다. // 오래(staleSeconds) 안 끝난 기록(풀 반환으로 코루틴이 끊긴 경우)은 버리고 새로 잡는다 · 스폰(풀 재사용)되면 기록을 지운다. // 🔴 Debug.LogError 금지(원본 팝업). // ───────────────────────────────────────────────────────────────────────────── using System.Collections.Generic; using UnityEngine; using WL.Combat.Core; namespace WL.Combat.Reaction { public static class WLActorScale { const float StaleSeconds = 5f; sealed class Entry { public Vector3 rest; public int count; public float touched; } static readonly Dictionary s_map = new Dictionary(32); public static int Begins, Ends, StaleReset; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)] static void Register() { CombatEvents.Spawned.Add(OnSpawned); } static void OnSpawned(in SpawnedEvent e) { if (e.actor != null) s_map.Remove(e.actor.transform); } /// 효과 시작 — 쉬는 크기(진행 중인 효과가 있으면 그 기억) 반환. public static Vector3 Begin(Transform tf) { if (tf == null) return Vector3.one; Entry e; if (!s_map.TryGetValue(tf, out e)) { e = new Entry { rest = tf.localScale }; s_map[tf] = e; } else if (e.count <= 0 || Time.unscaledTime - e.touched > StaleSeconds) { e.rest = e.count <= 0 ? tf.localScale : e.rest; if (e.count > 0) StaleReset++; e.count = 0; } e.count++; e.touched = Time.unscaledTime; Begins++; return e.rest; } /// 진행 중인 효과가 있으면 쉬는 크기, 없으면 지금 크기. public static Vector3 Rest(Transform tf) { Entry e; return tf != null && s_map.TryGetValue(tf, out e) && e.count > 0 ? e.rest : (tf != null ? tf.localScale : Vector3.one); } public static bool Active(Transform tf) { Entry e; return tf != null && s_map.TryGetValue(tf, out e) && e.count > 0; } /// 효과 끝 — 마지막 효과면 쉬는 크기로 되돌린다. public static void End(Transform tf) { Entry e; if (tf == null || !s_map.TryGetValue(tf, out e)) return; e.count--; e.touched = Time.unscaledTime; Ends++; if (e.count <= 0) { tf.localScale = e.rest; s_map.Remove(tf); } } public static void Clear() { s_map.Clear(); } } }