// PD #797 — WLHitFeelSettings 에셋 생성/확인/조정 (Edit 모드 전용 · 리컴파일 완료 후 실행) // 확정값은 Edit 모드에서 굽고 Dump 로 디스크와 대조한다(Play 중 에셋 인스턴스 수정 금지). using System.Text; using UnityEngine; using UnityEditor; public static class WL797_MakeAsset { const string Dir1 = "Assets/WL/Feel"; const string Dir2 = "Assets/WL/Feel/Settings"; const string Dir3 = "Assets/WL/Feel/Settings/Resources"; const string Dir4 = "Assets/WL/Feel/Settings/Resources/WL"; const string Path = "Assets/WL/Feel/Settings/Resources/WL/WLHitFeelSettings.asset"; static void EnsureFolder(string parent, string leaf) { var full = parent + "/" + leaf; if (!AssetDatabase.IsValidFolder(full)) AssetDatabase.CreateFolder(parent, leaf); } public static object Create() { EnsureFolder("Assets/WL", "Feel"); EnsureFolder(Dir1, "Settings"); EnsureFolder(Dir2, "Resources"); EnsureFolder(Dir3, "WL"); var so = AssetDatabase.LoadAssetAtPath(Path); bool created = false; if (so == null) { so = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(so, Path); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); created = true; } return (created ? "CREATED " : "EXISTS ") + Path + "\n" + Dump(); } /// 디스크의 확정값을 그대로 읽어 출력한다(Play 중 변경이 디스크로 새지 않았는지 대조용). public static object Dump() { var so = AssetDatabase.LoadAssetAtPath(Path); if (so == null) return "MISSING " + Path; var sb = new StringBuilder(); sb.AppendLine("── WLHitFeelSettings (disk) ──"); sb.AppendLine("enabled=" + so.enabled + " throttleSeconds=" + so.throttleSeconds); sb.AppendLine("① hitStop: enabled=" + so.hitStopEnabled + " mode=" + so.hitStopMode + " dur=" + so.hitStopDuration + " killDur=" + so.hitStopKillDuration + " scale=" + so.hitStopTimeScale + " max=" + so.hitStopMax + " minTS=" + so.hitStopMinTimescale); sb.AppendLine("② shake: enabled=" + so.cameraShakeEnabled + " amp=" + so.shakeAmplitude + " dur=" + so.shakeDuration + " freq=" + so.shakeFrequency + " axis=" + so.shakeAxisWeight + " killMul=" + so.shakeKillMultiplier + " suppressLegacy=" + so.suppressLegacyShake); sb.AppendLine("③ punch: enabled=" + so.scalePunchEnabled + " punch=" + so.scalePunch + " dur=" + so.scalePunchDuration + " skipBoss=" + so.skipPunchOnBoss + " skipKill=" + so.skipPunchOnKill); sb.AppendLine("④ flash: enabled=" + so.flashEnabled + " color=" + so.flashColor + " dur=" + so.flashDuration); sb.AppendLine("⑤ haptic: enabled=" + so.hapticEnabled); sb.AppendLine("log: " + so.logHits); return sb.ToString(); } /// 세기 프리셋. args: "weak" | "mid" | "midplus" | "strong" | "off" public static object Preset(string name) { var so = AssetDatabase.LoadAssetAtPath(Path); if (so == null) return "MISSING " + Path; switch ((name ?? "").ToLowerInvariant()) { case "off": so.enabled = false; break; case "weak": // A — Feel 공식 Barbarians 데모와 같은 강도 so.enabled = true; so.hitStopDuration = 0.02f; so.hitStopKillDuration = 0.035f; so.shakeAmplitude = 0.08f; so.shakeDuration = 0.10f; so.scalePunch = 1.08f; break; case "mid": // B — 발주 기본값 (권고) so.enabled = true; so.hitStopDuration = 0.03f; so.hitStopKillDuration = 0.05f; so.shakeAmplitude = 0.10f; so.shakeDuration = 0.12f; so.scalePunch = 1.12f; break; case "midplus": // B+ — PD 2026-09-07 "현재보다 미세하게 강하게" (mid 와 strong 의 중간) case "mid+": so.enabled = true; so.hitStopDuration = 0.04f; so.hitStopKillDuration = 0.065f; so.shakeAmplitude = 0.11f; so.shakeDuration = 0.12f; so.scalePunch = 1.14f; break; case "strong": // C — 발주 상한 so.enabled = true; so.hitStopDuration = 0.05f; so.hitStopKillDuration = 0.08f; so.shakeAmplitude = 0.12f; so.shakeDuration = 0.12f; so.scalePunch = 1.16f; break; default: return "UNKNOWN preset '" + name + "' (weak|mid|midplus|strong|off)"; } EditorUtility.SetDirty(so); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); return "PRESET " + name + " applied\n" + Dump(); } /// 진단 로그 on/off. args: true|false public static object SetLog(bool on) { var so = AssetDatabase.LoadAssetAtPath(Path); if (so == null) return "MISSING " + Path; so.logHits = on; EditorUtility.SetDirty(so); AssetDatabase.SaveAssets(); return "logHits=" + so.logHits; } /// 플래시 on/off (PD 옵션). public static object SetFlash(bool on) { var so = AssetDatabase.LoadAssetAtPath(Path); if (so == null) return "MISSING " + Path; so.flashEnabled = on; EditorUtility.SetDirty(so); AssetDatabase.SaveAssets(); return "flashEnabled=" + so.flashEnabled; } }