Project_WL/AgentScripts/WL772_MatFix.cs

86 lines
4.0 KiB
C#

// WL772_MatFix.cs — PD 지시 #772 : 맵 프리팹의 마젠타(셰이더 깨짐 / null 머티리얼) 진단 + URP 업그레이드
// 진단 : unity command run_script --file AgentScripts/WL772_MatFix.cs --entry WL772_MatFix.Diag --args '["Assets/Res_Addr/Map/WL_Nature03.prefab"]'
// 수리 : ... --entry WL772_MatFix.Fix --args '["Assets/Res_Addr/Map/WL_Nature03.prefab"]'
// Fix 는 머티리얼 에셋의 셰이더만 Built-in → URP 로 승격한다(MaterialUpgrader). 프리팹은 건드리지 않는다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Rendering;
#endif
public static class WL772_MatFix
{
#if UNITY_EDITOR
static readonly string[] BuiltIn = { "Standard", "Standard (Specular setup)", "Legacy Shaders/", "Mobile/", "Particles/", "Nature/", "Unlit/Texture", "Unlit/Color", "Unlit/Transparent" };
static List<Material> Collect(string prefabPath, StringBuilder sb)
{
var bad = new List<Material>();
var root = PrefabUtility.LoadPrefabContents(prefabPath);
try
{
var seen = new HashSet<string>();
foreach (var r in root.GetComponentsInChildren<Renderer>(true))
foreach (var m in r.sharedMaterials)
{
if (m == null) { if (seen.Add("NULLSLOT:" + r.name)) sb.AppendLine(" null 머티리얼 슬롯 — " + r.name); continue; }
var sn = m.shader != null ? m.shader.name : "(shader null)";
bool broken = m.shader == null || sn == "Hidden/InternalErrorShader" || BuiltIn.Any(b => sn.StartsWith(b));
if (!broken) continue;
var path = AssetDatabase.GetAssetPath(m);
if (!seen.Add(path + "|" + sn)) continue;
sb.AppendLine(string.Format(" [{0}] {1} ← {2}", sn, m.name, path));
if (!string.IsNullOrEmpty(path) && path.StartsWith("Assets/")) bad.Add(m);
}
}
finally { PrefabUtility.UnloadPrefabContents(root); }
return bad;
}
public static object Diag(string prefabPath)
{
var sb = new StringBuilder("# " + prefabPath + "\n");
var bad = Collect(prefabPath, sb);
sb.AppendLine("수리 대상 머티리얼 = " + bad.Count);
return sb.ToString();
}
public static object Fix(string prefabPath)
{
var sb = new StringBuilder("# " + prefabPath + "\n");
var bad = Collect(prefabPath, sb);
int ok = 0, fail = 0;
foreach (var m in bad)
{
var before = m.shader != null ? m.shader.name : "(null)";
try
{
MaterialUpgrader.Upgrade(m, new UnityEditor.Rendering.Universal.StandardUpgrader(before), MaterialUpgrader.UpgradeFlags.None);
}
catch { }
if (m.shader == null || m.shader.name == before || m.shader.name == "Hidden/InternalErrorShader")
{
// 폴백: URP Lit 로 직접 지정하고 주요 값을 옮긴다
var col = m.HasProperty("_Color") ? m.GetColor("_Color") : Color.white;
var tex = m.HasProperty("_MainTex") ? m.GetTexture("_MainTex") : null;
var lit = Shader.Find("Universal Render Pipeline/Lit");
if (lit == null) { fail++; sb.AppendLine(" FAIL(URP Lit 없음) " + m.name); continue; }
m.shader = lit;
if (m.HasProperty("_BaseColor")) m.SetColor("_BaseColor", col);
if (tex != null && m.HasProperty("_BaseMap")) m.SetTexture("_BaseMap", tex);
}
EditorUtility.SetDirty(m);
ok++;
sb.AppendLine(string.Format(" {0} : {1} -> {2}", m.name, before, m.shader != null ? m.shader.name : "(null)"));
}
AssetDatabase.SaveAssets();
sb.AppendLine(string.Format("업그레이드 {0} · 실패 {1}", ok, fail));
return sb.ToString();
}
#endif
}