Project_WL/AgentScripts/WL785_Setup.cs

181 lines
9.2 KiB
C#
Raw Permalink Normal View History

WL 리뉴얼 세션 2026-09-06~07 (#760~#800) — 전투·배경·UI·타격감 (조직 PD 로그 #746~#800 · 대화로그 §14~§24) - 전투: Knight@Attack1~3_S 3콤보(4 컨트롤러·클래스별 서브클립) · 타겟팅 4규칙(정면 우선·재타겟·즉시 공격·어그로 금지 · WLTargetingSettings) · 대쉬 후 공격(Stander@Chase_Start · DashDriver · 5 m · 사정거리+0.8 · 근거리 적 우선) · 공격 이동 FrameTable(발 접지 실측 표 · AttackRootMotion) · 충돌 반경/투사체 0.3 배(WLCollisionTuning) · 무적(임시)·펫 금지(WLGameplaySettings) - 검기: NamuFX Slash_B 배리언트 Effect_WLSwingArc 원 피팅 정합 배치 + 캘리브레이션(SlashArcMeasure · SlashTrailSettings) · 찌르기 Effect_WLStab 대기 · 램프 리본(BladeTrail · WL_BladeRibbon.shader · T_WL_BladeRibbonRamp) 보존(drawRibbon 0) - 타격감: Assets/WL/Feel(WLHitFeel · 히트스톱 0.03 · 셰이크 0.10 m · 몹 펀치 1.12 · Actor.Get_Damage 훅 1줄 · 원본 RealCamera 셰이크 결함 대체) - 배경/맵: LMHPOLY Demo_01~10 → WL_Nature01~10(프리팹·씬·NavMesh·스포너·BattleMapConfig) · 물(ToonWaterU) · 포스트 블룸 0.9/0.3 · 잔디(BruteForce·드레싱) 제거 · 마젠타 머티리얼 URP 변환 - UI: 세로 HUD(WL_HUD · 하단 5메뉴 폭 전체 · 채팅/전투 패드 숨김 · WLIngameUiOverride) · Title/TitleInfo 1080×1920 Expand + 배경 높이 fit(WLBackgroundFit) · 로딩 SortOrder_5(WLRawImageAspectSync · 초점표 8장) · Loading1~8 ASTC 6×6 - 도구: AgentScripts/*(LightProbe · WL_MapSwitch · WL760~WL800 프로브/집행/검증 · 상단 사용법 주석) · 에디터 락 프로토콜 파일(staging) - 제외(별도 커밋 예정): Assets/LMHPOLY(703 MB) · Assets/Feel(422 MB) · Assets/Shinabro(300 MB) — 에셋 스토어/구 WL 팩 원본 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 23:24:25 +00:00
// WL785_Setup.cs — PD 지시 #785 무기 궤적 리본 집행 (에디트 모드 · Assets 수정)
// unity command run_script --file AgentScripts/WL785_Setup.cs --entry WL785_Setup.MakeMaterial
// unity command run_script --file AgentScripts/WL785_Setup.cs --entry WL785_Setup.ApplySettings
// unity command run_script --file AgentScripts/WL785_Setup.cs --entry WL785_Setup.Dump
//
// 왜 스크립트로 만드는가:
// Gradient 는 .asset YAML 로 손으로 쓰기 위험하다(colorKeys/alphaKeys 직렬화가 버전마다
// 미묘하게 다르다). 머티리얼도 셰이더 fileID 를 손으로 넣어야 해 오타 1글자가 곧 분홍 머티리얼이다.
// → 공개 API 로 만들고 SetDirty/SaveAssets 로 굽는다.
//
// 값의 SOT 는 이 스크립트가 아니라 **SlashTrailSettings.asset** 이다. 이 스크립트는
// PD 참고 이미지에 맞춘 "기본값 1회 주입"만 한다. 이후 튜닝은 인스펙터에서 한다(C45).
using System.Text;
using UnityEditor;
using UnityEngine;
public static class WL785_Setup
{
const string ShaderPath = "Assets/WL/Combat/Shaders/WL_BladeRibbon.shader";
const string MatPath = "Assets/WL/Combat/Materials/M_WL_BladeRibbon.mat";
const string SettingsPath = "Assets/WL/Settings/Resources/WL/SlashTrailSettings.asset";
public static object MakeMaterial()
{
if (EditorApplication.isPlaying) return "ABORT: Play 중";
var sh = AssetDatabase.LoadAssetAtPath<Shader>(ShaderPath);
if (sh == null) return "ABORT: 셰이더 로드 실패 " + ShaderPath;
var mat = AssetDatabase.LoadAssetAtPath<Material>(MatPath);
bool created = false;
if (mat == null)
{
mat = new Material(sh);
AssetDatabase.CreateAsset(mat, MatPath);
created = true;
}
else mat.shader = sh;
// 기본값 = 프리멀티플라이 알파(One / OneMinusSrcAlpha). 양면. 텍스처 없음(흰색).
// 순수 가산(One/One)은 WL_Nature 의 밝은 모래 위에서 색이 전부 흰색으로 날아갔다(실측).
mat.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One);
mat.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
mat.SetFloat("_Cull", (float)UnityEngine.Rendering.CullMode.Off);
mat.SetFloat("_EdgeSoftness", 0.24f);
mat.SetFloat("_HeadSoftness", 0.03f);
mat.SetFloat("_TailSoftness", 0.16f);
mat.SetFloat("_Intensity", 1.0f);
mat.SetFloat("_AlphaCutoff", 0.008f);
mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
EditorUtility.SetDirty(mat);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return (created ? "생성 " : "갱신 ") + MatPath + " shader=" + mat.shader.name +
" pass=" + mat.passCount + " queue=" + mat.renderQueue;
}
public static object ApplySettings()
{
if (EditorApplication.isPlaying) return "ABORT: Play 중";
var s = AssetDatabase.LoadAssetAtPath<WL.Combat.SlashTrailSettings>(SettingsPath);
if (s == null) return "ABORT: 설정 에셋 로드 실패 " + SettingsPath;
var mat = AssetDatabase.LoadAssetAtPath<Material>(MatPath);
if (mat == null) return "ABORT: 머티리얼이 아직 없다 — MakeMaterial 먼저";
var sb = new StringBuilder();
// ── 리본 ON · 크레센트 프리팹 경로 폐기 (#761/#777 방식 종료) ──────────
s.drawRibbon = true;
s.burstMode = WL.Combat.BurstMode.None; // ShowEffect 프리팹 스폰 안 함 = 이중 연출 제거
s.suppressMode = WL.Combat.SuppressMode.CrescentOnly; // 억제할 프리팹 자체가 없다
// ── 형상 : 폭 = 손잡이~검끝 전체(PD "검 끝~손잡이 폭") ────────────────
s.widthScale = 1f;
s.tailWidthRatio = 1f; // 테이퍼 없음 — 폭 일정
s.tipExtendRatio = 0f;
s.maxSamples = 64; // PD 예산 상한 = 세그먼트 64
s.minSampleDistance = 0.010f;
s.maxSegmentDistance = 0.22f;
s.maxSubSteps = 3;
// UV : 새 리본 셰이더는 v 로 가장자리를 페이드한다. 구 시트 텍스처용 창(0.667~1)이
// 남아 있으면 칼끝 절반이 통째로 지워진다 → 0~1 전체로 되돌린다.
s.uvUMin = 0f; s.uvUMax = 1f;
s.uvVMin = 0f; s.uvVMax = 1f;
// ── 수명 : PD 지시 0.15~0.25 s ────────────────────────────────────────
// 0.22 는 스윙이 빠를 때 꼬리가 화면 밖까지 길어져(실측) 참고 이미지의 짧은 호와 달랐다.
s.fadeSeconds = 0.20f;
s.fadeHoldRatio = 0.55f;
// ── 머티리얼 : 리본 전용 1장 = 드로우 1회 ─────────────────────────────
s.materialAdditive = mat;
s.materialAlpha = null;
s.alsoApplyColorViaPropertyBlock = false;
s.writeCustomDataChannels = false;
// ── 색 : 참고 이미지 (안쪽·머리 주황/노랑 → 바깥·꼬리 파랑/보라) ──────
s.useGradients = true;
// 0.5(반반)는 잔상축의 보라와 칼날축의 노랑을 반반 섞어 **회색**을 만든다 — 리본이
// 하얗게 보이던 실측 원인이었다. 색조는 칼날축(안쪽 주황 → 바깥 파랑)이 주도하게 둔다.
s.bladeGradientWeight = 0.8f;
s.colorIntensity = 1.0f;
var gSwing = new Gradient();
gSwing.SetKeys(
new[]
{
new GradientColorKey(new Color(0.42f, 0.16f, 0.90f), 0.00f), // 꼬리 = 보라
new GradientColorKey(new Color(0.20f, 0.45f, 1.00f), 0.32f), // 파랑
new GradientColorKey(new Color(1.00f, 0.52f, 0.14f), 0.72f), // 주황
new GradientColorKey(new Color(1.00f, 0.85f, 0.42f), 1.00f), // 머리 = 노랑
},
new[]
{
new GradientAlphaKey(0.00f, 0.00f),
new GradientAlphaKey(0.68f, 0.18f),
new GradientAlphaKey(0.95f, 0.55f),
new GradientAlphaKey(0.95f, 1.00f),
});
s.gradientAlongSwing = gSwing;
var gBlade = new Gradient();
gBlade.SetKeys(
new[]
{
new GradientColorKey(new Color(1.00f, 0.72f, 0.22f), 0.00f), // 손잡이(안쪽) = 주황/노랑
new GradientColorKey(new Color(1.00f, 0.42f, 0.18f), 0.45f),
new GradientColorKey(new Color(0.34f, 0.30f, 1.00f), 1.00f), // 칼끝(바깥) = 파랑/보라
},
new[]
{
new GradientAlphaKey(1.00f, 0.00f),
new GradientAlphaKey(1.00f, 0.60f),
new GradientAlphaKey(0.85f, 1.00f),
});
s.gradientAlongBlade = gBlade;
// ── 클래스 오버라이드 : 색은 전역 그라디언트로 통일, 폭만 전체로 ──────
if (s.classOverrides != null)
foreach (var ov in s.classOverrides)
{
if (ov == null) continue;
ov.overrideLook = false; // 전역 그라디언트를 그대로 쓴다
ov.widthScale = 1f;
sb.AppendLine(" class " + ov.classId + " overrideLook=0 widthScale=1");
}
EditorUtility.SetDirty(s);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
sb.Insert(0, "ApplySettings OK drawRibbon=1 burstMode=None widthScale=1 tailWidthRatio=1 " +
"life=" + s.fadeSeconds + "s maxSamples=" + s.maxSamples +
" mat=" + mat.name + "\n");
return sb.ToString();
}
public static object Dump()
{
var s = AssetDatabase.LoadAssetAtPath<WL.Combat.SlashTrailSettings>(SettingsPath);
if (s == null) return "설정 에셋 없음";
var sb = new StringBuilder();
sb.AppendLine("drawRibbon=" + s.drawRibbon + " burstMode=" + s.burstMode +
" useGradients=" + s.useGradients + " intensity=" + s.colorIntensity);
sb.AppendLine("widthScale=" + s.widthScale + " tailWidthRatio=" + s.tailWidthRatio +
" maxSamples=" + s.maxSamples + " life=" + s.fadeSeconds + " hold=" + s.fadeHoldRatio);
sb.AppendLine("maxSegmentDistance=" + s.maxSegmentDistance + " maxSubSteps=" + s.maxSubSteps +
" minSampleDistance=" + s.minSampleDistance);
sb.AppendLine("matAdd=" + (s.materialAdditive != null ? s.materialAdditive.name + " / " + s.materialAdditive.shader.name : "(null)") +
" matAlpha=" + (s.materialAlpha != null ? s.materialAlpha.name : "(null)"));
if (s.gradientAlongSwing != null)
for (float t = 0f; t <= 1.001f; t += 0.25f)
sb.AppendLine(" swing t=" + t.ToString("0.00") + " -> " + s.gradientAlongSwing.Evaluate(t));
if (s.gradientAlongBlade != null)
for (float t = 0f; t <= 1.001f; t += 0.5f)
sb.AppendLine(" blade t=" + t.ToString("0.00") + " -> " + s.gradientAlongBlade.Evaluate(t));
return sb.ToString();
}
}