// ───────────────────────────────────────────────────────────────────────────── // WLCharacterPalette.cs — 팔레트 아틀라스 UV 를 런타임에 끼운다 (WL-814x) // // PD 지시 #814 · 발주서 WL-814x // // ■ 왜 이렇게 하나 // 화면 속 캐릭터는 키 117 px 뿐이라 텍셀 수천 개가 평균 나 화면 1 px 이 된다(814u 실측). // 그래서 텍스처를 아무리 곱게 그려도 「흐린 사진」이 된다. // → 메시의 각 덩어리 UV 를 **팔레트 텍스처의 칸 한가운데**로 보내면 그 덩어리는 // 아무리 축소돼도 항상 단색이다(평균 날 디테일이 애초에 없다). // // ■ 되돌리기 // WLCharacterPaletteSettings.enabled_ = 0 → 아무것도 안 한다 = 814s + 814t 상태 100 %. // // ■ 성능 / GC // Awake 1회. 렌더러 수(7)만큼만 돈다. 바꿀 것이 없으면 대입도 하지 않는다. // // 🔴 Debug.LogError / Debug.LogException 을 쓰지 않는다(813z 규칙). // ───────────────────────────────────────────────────────────────────────────── using System.Collections.Generic; using UnityEngine; namespace WL.Look.Character { public static class WLCharacterPalette { // 진단(프로브가 읽는다) public static int AppliedRenderers, AppliedMeshes; public static string LastLog = ""; static readonly List s_buf = new List(16); /// SO 가 켜져 있으면 팔레트 메시·머티리얼로 갈아끼운다. public static void Apply(GameObject root) { AppliedRenderers = 0; AppliedMeshes = 0; var cfg = WLCharacterPaletteSettings.Instance; if (cfg == null || root == null || cfg.enabled_ == 0) { LastLog = cfg == null ? "SO 없음 → 적용 0" : "enabled_=0 → 적용 0 (814s+814t 상태)"; return; } var names = cfg.rendererNames; if (names == null || names.Length == 0) { LastLog = "표 비어 있음 → 적용 0"; return; } s_buf.Clear(); root.GetComponentsInChildren(true, s_buf); for (int ri = 0; ri < s_buf.Count; ri++) { var r = s_buf[ri]; if (r == null) continue; int idx = IndexOf(names, r.name); if (idx < 0) continue; // ① 메시 — 스킨 메시는 본/바인드포즈가 원본과 같으므로 그대로 갈아끼워진다. var smr = r as SkinnedMeshRenderer; if (smr != null && cfg.paletteMeshes != null && idx < cfg.paletteMeshes.Length) { var m = cfg.paletteMeshes[idx]; if (m != null && smr.sharedMesh != m) { smr.sharedMesh = m; AppliedMeshes++; } } // ② 머티리얼 if (cfg.paletteMaterials != null && idx < cfg.paletteMaterials.Length) { var want = cfg.paletteMaterials[idx]; if (want != null) { var mats = r.sharedMaterials; bool changed = false; for (int si = 0; si < mats.Length; si++) if (mats[si] != want) { mats[si] = want; changed = true; } if (changed) { r.sharedMaterials = mats; AppliedRenderers++; } } } } LastLog = "렌더러 " + AppliedRenderers + " · 메시 " + AppliedMeshes; if (cfg.verboseLog != 0) Debug.Log("[WL814x CharacterPalette] " + LastLog); } static int IndexOf(string[] names, string n) { for (int i = 0; i < names.Length; i++) if (names[i] == n) return i; return -1; } } }