178 lines
12 KiB
C#
178 lines
12 KiB
C#
// WL842_StatusPrefabs.cs — #842 상태이상 VFX 준비(에디터 전용 · Play 밖에서)
|
|
// ① ConvertLegacy : Master Stylized FX 안에서 아직 내장(Built-in) 셰이더(Particles/Standard Unlit 211 · Surface 210 · Standard 46)를 쓰는 머티리얼을 URP 로 변환.
|
|
// 동봉 MSFURP 패키지가 46장을 빠뜨린다(DizzyStar·SleepSymbol·BubbleSymbol·Spike3D 등 = 우리가 쓰는 것들). _Mode(2 Fade·4 Additive) 와 블렌드 값을 그대로 옮긴다.
|
|
// ② Build : Prefabs/Buffs·Hit 의 원본 프리팹을 복제해 Resources/WL/Status/<name>.prefab 으로 저장(독은 보라 틴트). 원본 에셋 무수정.
|
|
// unity command run_script --file AgentScripts/WL842_StatusPrefabs.cs --entry WL842_StatusPrefabs.ConvertLegacy
|
|
// unity command run_script --file AgentScripts/WL842_StatusPrefabs.cs --entry WL842_StatusPrefabs.Build --args '[]'
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
public static class WL842_StatusPrefabs
|
|
{
|
|
const string AssetRoot = "Assets/ResWork/VFX/MasterStylizedFX";
|
|
const string OutDir = "Assets/WL/Combat/Status/Resources/WL/Status";
|
|
const string BuiltinGuid = "0000000000000000f000000000000000";
|
|
|
|
// 출력 이름 → (원본 프리팹 경로 · 틴트(없으면 null))
|
|
static readonly (string name, string src, Color? tint)[] Map =
|
|
{
|
|
("WL_Status_Stun", "Prefabs/Buffs/Dizziness.prefab", null),
|
|
("WL_Status_Sleep", "Prefabs/Buffs/Sleeping.prefab", null),
|
|
("WL_Status_SpeedUp", "Prefabs/Buffs/EnhanceBuff.prefab", null), // 꺽새(^) 상승
|
|
("WL_Status_SpeedDown", "Prefabs/Buffs/Debuff.prefab", null), // 꺽새 하락
|
|
("WL_Status_StatUp", "Prefabs/Buffs/EnhanceBuff2.prefab", null), // 화살표 상승
|
|
("WL_Status_Poison", "Prefabs/Buffs/DrunkBuff.prefab", new Color(0.72f, 0.30f, 1f, 1f)), // 방울+연기 → 보라
|
|
("WL_Status_Bleed", "Prefabs/Hit/OrangeSlashHit.prefab", null), // 스크린샷 대조 후 교체 가능(SetBleedSource)
|
|
};
|
|
|
|
public static string ConvertLegacy()
|
|
{
|
|
if (EditorApplication.isPlaying) return "skipped: playing";
|
|
var sb = new StringBuilder();
|
|
int n = 0, skipped = 0;
|
|
var unlit = Shader.Find("Universal Render Pipeline/Particles/Unlit");
|
|
var lit = Shader.Find("Universal Render Pipeline/Lit");
|
|
if (unlit == null || lit == null) return "URP shaders not found";
|
|
foreach (var guid in AssetDatabase.FindAssets("t:Material", new[] { AssetRoot + "/Materials" }))
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guid);
|
|
var txt = System.IO.File.ReadAllText(path);
|
|
var m = System.Text.RegularExpressions.Regex.Match(txt, @"m_Shader: \{fileID: (\d+), guid: " + BuiltinGuid);
|
|
if (!m.Success) { skipped++; continue; }
|
|
int fid = int.Parse(m.Groups[1].Value);
|
|
var mat = AssetDatabase.LoadAssetAtPath<Material>(path);
|
|
if (mat == null) continue;
|
|
var mainTex = mat.HasProperty("_MainTex") ? mat.GetTexture("_MainTex") : null;
|
|
var scale = mat.HasProperty("_MainTex") ? mat.GetTextureScale("_MainTex") : Vector2.one;
|
|
var offset = mat.HasProperty("_MainTex") ? mat.GetTextureOffset("_MainTex") : Vector2.zero;
|
|
var color = mat.HasProperty("_Color") ? mat.GetColor("_Color") : Color.white;
|
|
if (fid == 46)
|
|
{ // Standard → Lit
|
|
mat.shader = lit;
|
|
mat.SetTexture("_BaseMap", mainTex); mat.SetColor("_BaseColor", color);
|
|
sb.AppendLine("lit " + path.Substring(AssetRoot.Length + 1));
|
|
EditorUtility.SetDirty(mat); n++; continue;
|
|
}
|
|
// Particles/Standard Unlit(211)·Surface(210) → Particles/Unlit · 블렌드 값(_Mode·_SrcBlend·_DstBlend·_ZWrite·_Cull·_ColorMode) 승계
|
|
int mode = mat.HasProperty("_Mode") ? (int)mat.GetFloat("_Mode") : 2;
|
|
float src = mat.HasProperty("_SrcBlend") ? mat.GetFloat("_SrcBlend") : 5f, dst = mat.HasProperty("_DstBlend") ? mat.GetFloat("_DstBlend") : 10f;
|
|
float zw = mat.HasProperty("_ZWrite") ? mat.GetFloat("_ZWrite") : 0f, cull = mat.HasProperty("_Cull") ? mat.GetFloat("_Cull") : 2f;
|
|
float colorMode = mat.HasProperty("_ColorMode") ? mat.GetFloat("_ColorMode") : 0f;
|
|
float soft = mat.HasProperty("_SoftParticlesEnabled") ? mat.GetFloat("_SoftParticlesEnabled") : 0f;
|
|
mat.shader = unlit;
|
|
mat.SetTexture("_BaseMap", mainTex); mat.SetTextureScale("_BaseMap", scale); mat.SetTextureOffset("_BaseMap", offset);
|
|
mat.SetColor("_BaseColor", color);
|
|
bool opaque = mode == 0 || mode == 1;
|
|
mat.SetFloat("_Surface", opaque ? 0f : 1f);
|
|
mat.SetFloat("_Blend", mode == 4 ? 2f : mode == 3 ? 1f : mode == 6 ? 3f : 0f);
|
|
mat.SetFloat("_AlphaClip", mode == 1 ? 1f : 0f);
|
|
mat.SetFloat("_SrcBlend", src); mat.SetFloat("_DstBlend", dst);
|
|
if (mat.HasProperty("_SrcBlendAlpha")) { mat.SetFloat("_SrcBlendAlpha", src); mat.SetFloat("_DstBlendAlpha", dst); }
|
|
mat.SetFloat("_ZWrite", zw); mat.SetFloat("_Cull", cull);
|
|
mat.SetFloat("_ColorMode", colorMode);
|
|
mat.SetFloat("_SoftParticlesEnabled", soft);
|
|
if (opaque) { mat.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); mat.SetOverrideTag("RenderType", mode == 1 ? "TransparentCutout" : "Opaque"); mat.renderQueue = mode == 1 ? 2450 : 2000; }
|
|
else { mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); mat.SetOverrideTag("RenderType", "Transparent"); mat.renderQueue = 3000; }
|
|
if (mode == 3) mat.EnableKeyword("_ALPHAPREMULTIPLY_ON"); else mat.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
|
if (mode == 6) mat.EnableKeyword("_ALPHAMODULATE_ON"); else mat.DisableKeyword("_ALPHAMODULATE_ON");
|
|
if (mode == 1) mat.EnableKeyword("_ALPHATEST_ON"); else mat.DisableKeyword("_ALPHATEST_ON");
|
|
if (soft > 0f) mat.EnableKeyword("_SOFTPARTICLES_ON"); else mat.DisableKeyword("_SOFTPARTICLES_ON");
|
|
mat.SetShaderPassEnabled("ShadowCaster", false);
|
|
EditorUtility.SetDirty(mat); n++;
|
|
sb.AppendLine("unlit " + path.Substring(AssetRoot.Length + 1) + " mode=" + mode + " blend=" + src + "/" + dst);
|
|
}
|
|
AssetDatabase.SaveAssets();
|
|
return "converted " + n + " (already URP " + skipped + ")\n" + sb;
|
|
}
|
|
|
|
public static string Build()
|
|
{
|
|
if (EditorApplication.isPlaying) return "skipped: playing";
|
|
if (!AssetDatabase.IsValidFolder(OutDir)) System.IO.Directory.CreateDirectory(OutDir);
|
|
AssetDatabase.Refresh();
|
|
var sb = new StringBuilder();
|
|
foreach (var e in Map)
|
|
{
|
|
string srcPath = AssetRoot + "/" + e.src;
|
|
var src = AssetDatabase.LoadAssetAtPath<GameObject>(srcPath);
|
|
if (src == null) { sb.AppendLine("missing " + srcPath); continue; }
|
|
var inst = (GameObject)PrefabUtility.InstantiatePrefab(src);
|
|
PrefabUtility.UnpackPrefabInstance(inst, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
|
inst.name = e.name;
|
|
inst.transform.position = Vector3.zero; inst.transform.rotation = Quaternion.identity; inst.transform.localScale = Vector3.one;
|
|
int ps = 0;
|
|
foreach (var p in inst.GetComponentsInChildren<ParticleSystem>(true))
|
|
{
|
|
ps++;
|
|
{ var main = p.main; main.scalingMode = ParticleSystemScalingMode.Hierarchy; } // 트랜스폼 스케일이 파티클 크기에도 먹게(기본 Shape 는 방출 범위만 줄어 별이 원래 크기로 남는다 · 2026-10-11 실측)
|
|
if (e.tint.HasValue)
|
|
{
|
|
var main = p.main; var sc = main.startColor;
|
|
sc.mode = ParticleSystemGradientMode.Color; sc.color = e.tint.Value; main.startColor = sc;
|
|
var col = p.colorOverLifetime;
|
|
if (col.enabled) { var g = col.color; if (g.mode == ParticleSystemGradientMode.Gradient && g.gradient != null) { var grad = g.gradient; var keys = grad.colorKeys; for (int i = 0; i < keys.Length; i++) keys[i].color = e.tint.Value; grad.SetKeys(keys, grad.alphaKeys); g.gradient = grad; col.color = g; } }
|
|
}
|
|
}
|
|
foreach (var l in inst.GetComponentsInChildren<Light>(true)) Object.DestroyImmediate(l); // 포인트 라이트는 치비 씬에서 과함
|
|
string outPath = OutDir + "/" + e.name + ".prefab";
|
|
PrefabUtility.SaveAsPrefabAsset(inst, outPath);
|
|
Object.DestroyImmediate(inst);
|
|
sb.AppendLine(e.name + " ← " + e.src + " ps=" + ps + (e.tint.HasValue ? " tint" : ""));
|
|
}
|
|
AssetDatabase.SaveAssets(); AssetDatabase.Refresh();
|
|
return sb.ToString();
|
|
}
|
|
|
|
// ── #843 임팩트 프리팹 사본 (Resources/WL/Impact/) ───────────────────────────
|
|
const string ImpactDir = "Assets/WL/Combat/Impact/Resources/WL/Impact";
|
|
static readonly (string name, string src)[] ImpactMap =
|
|
{
|
|
("WL_Impact_Hit_Blue", "Prefabs/Hit/SlashHitBlue.prefab"), // 검 피격 — 파란 별 + 긴 베기 줄 + 불꽃(PD 스크린샷)
|
|
("WL_Impact_Hit_Orange", "Prefabs/Hit/OrangeSlashHit.prefab"), // 해머 피격 — 주황 타격 폭발
|
|
("WL_Impact_Swing_Orange", "Prefabs/Slash/OrangeSlash.prefab"), // 해머 궤적 — 주황 회전 링(SlashHead·DustRing)
|
|
("WL_Impact_Ground", "Prefabs/GroundBlast/ExplosionBlast.prefab"), // 지면 충격파 — 주황 폭발 + 검은 파편 + 불꽃
|
|
};
|
|
public static string BuildImpact()
|
|
{
|
|
if (EditorApplication.isPlaying) return "skipped: playing";
|
|
if (!AssetDatabase.IsValidFolder(ImpactDir)) System.IO.Directory.CreateDirectory(ImpactDir);
|
|
AssetDatabase.Refresh();
|
|
var sb = new StringBuilder();
|
|
foreach (var e in ImpactMap)
|
|
{
|
|
var src = AssetDatabase.LoadAssetAtPath<GameObject>(AssetRoot + "/" + e.src);
|
|
if (src == null) { sb.AppendLine("missing " + e.src); continue; }
|
|
var inst = (GameObject)PrefabUtility.InstantiatePrefab(src);
|
|
PrefabUtility.UnpackPrefabInstance(inst, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
|
inst.name = e.name; inst.transform.position = Vector3.zero; inst.transform.rotation = Quaternion.identity; inst.transform.localScale = Vector3.one;
|
|
int ps = 0;
|
|
foreach (var p in inst.GetComponentsInChildren<ParticleSystem>(true)) { ps++; var main = p.main; main.scalingMode = ParticleSystemScalingMode.Hierarchy; }
|
|
foreach (var l in inst.GetComponentsInChildren<Light>(true)) Object.DestroyImmediate(l);
|
|
PrefabUtility.SaveAsPrefabAsset(inst, ImpactDir + "/" + e.name + ".prefab");
|
|
Object.DestroyImmediate(inst);
|
|
sb.AppendLine(e.name + " ← " + e.src + " ps=" + ps);
|
|
}
|
|
AssetDatabase.SaveAssets(); AssetDatabase.Refresh();
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>출혈 원본 프리팹 교체(스크린샷 대조 결과 반영). 예: SetBleedSource("Prefabs/Slash/OrangeSlash.prefab")</summary>
|
|
public static string SetBleedSource(string relPrefab)
|
|
{
|
|
if (EditorApplication.isPlaying) return "skipped: playing";
|
|
var src = AssetDatabase.LoadAssetAtPath<GameObject>(AssetRoot + "/" + relPrefab);
|
|
if (src == null) return "missing " + relPrefab;
|
|
var inst = (GameObject)PrefabUtility.InstantiatePrefab(src);
|
|
PrefabUtility.UnpackPrefabInstance(inst, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
|
inst.name = "WL_Status_Bleed"; inst.transform.position = Vector3.zero; inst.transform.rotation = Quaternion.identity; inst.transform.localScale = Vector3.one;
|
|
foreach (var p in inst.GetComponentsInChildren<ParticleSystem>(true)) { var main = p.main; main.scalingMode = ParticleSystemScalingMode.Hierarchy; }
|
|
foreach (var l in inst.GetComponentsInChildren<Light>(true)) Object.DestroyImmediate(l);
|
|
PrefabUtility.SaveAsPrefabAsset(inst, OutDir + "/WL_Status_Bleed.prefab");
|
|
Object.DestroyImmediate(inst);
|
|
AssetDatabase.SaveAssets();
|
|
return "bleed ← " + relPrefab;
|
|
}
|
|
}
|