// ───────────────────────────────────────────────────────────────────────────── // WLRangeRingSettings.cs — 플레이어 공격 사거리 원(반투명 흰색)의 튜닝 값(SO) // // PD 지시 #816 · 발주서 WL-816p // 「적 공격 가능한 사정거리에 있을 때는 플레이어의 주변에 공격 가능한 범위를 반투명한 흰색 원이 // 발생되고, 플레이어의 공격 사정거리 밖에 적이 3초 이상 있을 경우 흰색 원이 소멸되도록 해줘.」 // // 에셋 경로(고정): Assets/WL/Combat/Settings/Resources/WL/WLRangeRingSettings.asset // → Resources.Load("WL/WLRangeRingSettings") 로 1회 로드 후 캐시. // 에셋이 없거나 enabled = false 면 WLRangeRing 은 아무 것도 하지 않는다(원본 동작 100 %). // // 🔴 C45 — 사거리(반지름)는 이 에셋이 갖지 않는다. 게임이 실제 공격 판정에 쓰는 값 // (NavMeshAgent.stoppingDistance = table_classconfig.f_AttackRange + eStat.AttackRange_Up, // + WLTargetingSettings.immediateAttackMargin)을 런타임에 읽는다. 여기 있는 것은 배율·가산뿐이다. // // 🔴 어셈블리 주의: Assets/WL/Combat/ 에 .asmdef 를 만들지 말 것. // ───────────────────────────────────────────────────────────────────────────── using UnityEngine; namespace WL.Combat.RangeRing { [CreateAssetMenu(fileName = "WLRangeRingSettings", menuName = "WL/Range Ring Settings", order = 327)] public sealed class WLRangeRingSettings : ScriptableObject { public const string ResourcesPath = "WL/WLRangeRingSettings"; static WLRangeRingSettings s_cached; static bool s_lookupDone; public static WLRangeRingSettings Instance { get { if (!s_lookupDone) { s_cached = Resources.Load(ResourcesPath); s_lookupDone = true; } return s_cached; } } /// 테스트용 — 에셋 캐시를 버린다(에디터에서 값을 바꾸고 다시 읽을 때). public static void ClearCache() { s_cached = null; s_lookupDone = false; } [Header("① 켜기")] [Tooltip("0 이면 원을 만들지 않는다(원본 동작 100 %).")] public bool enabled = true; [Tooltip("1 이면 표시/소멸 시각을 Debug.Log 로 남긴다(검증용).")] public bool verboseLog = false; [Header("② 모양 · 색")] [Tooltip("원의 색. a = 반투명 정도(PD: 반투명한 흰색).")] public Color color = new Color(1f, 1f, 1f, 0.25f); [Tooltip("1 이면 테두리 링만, 0 이면 원판을 채운다.")] public bool ringOnly = false; [Tooltip("ringOnly = 1 일 때 링 두께(m).")] public float ringWidth = 0.18f; [Tooltip("원의 분할 수(많을수록 매끈하고 삼각형이 늘어난다). 모바일 예산 = 64.")] [Range(12, 256)] public int segments = 64; [Tooltip("바닥에서 띄우는 높이(m). Z-fighting 방지.")] public float yOffset = 0.03f; [Tooltip("렌더 큐(반투명 · 3000 이상). 지면 위·캐릭터 아래.")] public int renderQueue = 3040; [Tooltip("셰이더 후보(앞에서부터 Shader.Find).")] public string[] shaderNames = new[] { "Universal Render Pipeline/Unlit", "Unlit/Transparent", "Sprites/Default" }; [Tooltip("색 프로퍼티 후보(앞에서부터 FindPropertyIndex).")] public string[] colorProperties = new[] { "_BaseColor", "_Color", "_TintColor" }; [Header("③ 반지름 (SOT = 게임의 공격 판정 값 · 여기는 보정만)")] [Tooltip("실측 사거리에 곱하는 배율. 1 = 판정과 같은 크기.")] public float radiusScale = 1f; [Tooltip("실측 사거리에 더하는 값(m). 0 = 판정과 같은 크기.")] public float radiusBonus = 0f; [Tooltip("적 탐색 반경에 더하는 여유(m). 사거리 + 이 값 안의 적만 검사한다(전수 스캔 방지).")] public float searchPad = 2f; [Header("④ 시간")] [Tooltip("사거리 안에 적이 없어진 뒤 원이 버티는 시간(s). PD: 3초.")] public float graceSeconds = 3f; [Tooltip("나타나는 시간(s).")] public float fadeIn = 0.15f; [Tooltip("사라지는 시간(s).")] public float fadeOut = 0.4f; [Tooltip("적 검사 주기(s). 위치 추종은 매 프레임이라 이 값과 무관하다.")] public float pollInterval = 0.1f; } }