// WL-816a 실측 프로브 — 씬의 렌더링 구성 전수 + 에디트 모드 오프스크린 캡처 // 원본은 한 글자도 고치지 않는다(열기만 하고 저장 안 함). public static class WL816a_Probe { // ── 씬 1개 전수 조사 ──────────────────────────────────────────────── public static void Run() { string[] scenes = { "Assets/FarmingIsland/Scenes/Level01.unity", "Assets/3DPixelArtEnvironment/Demo/Demo.unity", }; var sb = new System.Text.StringBuilder(); for (int i = 0; i < scenes.Length; i++) Scan(scenes[i], sb); UnityEngine.Debug.Log(sb.ToString()); } public static void Scan(string path, System.Text.StringBuilder sb) { var sc = UnityEditor.SceneManagement.EditorSceneManager.OpenScene( path, UnityEditor.SceneManagement.OpenSceneMode.Single); Report(path, sb); } public static void Report(string label, System.Text.StringBuilder sb) { var rends = UnityEngine.Object.FindObjectsByType( UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); var mats = new System.Collections.Generic.Dictionary(); var shaders = new System.Collections.Generic.Dictionary(); var texMats = new System.Collections.Generic.List(); long tris = 0; int slots = 0; int nMeshRend = 0, nSkinned = 0, nPart = 0; for (int i = 0; i < rends.Length; i++) { var r = rends[i]; if (r is UnityEngine.ParticleSystemRenderer) { nPart++; continue; } var mr = r as UnityEngine.MeshRenderer; var sk = r as UnityEngine.SkinnedMeshRenderer; UnityEngine.Mesh mesh = null; if (mr != null) { nMeshRend++; var mf = r.GetComponent(); if (mf != null) mesh = mf.sharedMesh; } else if (sk != null) { nSkinned++; mesh = sk.sharedMesh; } if (mesh != null) { for (int s = 0; s < mesh.subMeshCount; s++) tris += mesh.GetIndexCount(s) / 3; } var ms = r.sharedMaterials; for (int m = 0; m < ms.Length; m++) { if (ms[m] == null) continue; slots++; int c; mats.TryGetValue(ms[m], out c); mats[ms[m]] = c + 1; string sn = ms[m].shader != null ? ms[m].shader.name : ""; int c2; shaders.TryGetValue(sn, out c2); shaders[sn] = c2 + 1; } } foreach (var kv in mats) { var m = kv.Key; string tex = ""; if (m.HasProperty("_BaseMap") && m.GetTexture("_BaseMap") != null) tex += "BaseMap=" + m.GetTexture("_BaseMap").name + " "; if (m.HasProperty("_MainTex") && m.GetTexture("_MainTex") != null) tex += "MainTex=" + m.GetTexture("_MainTex").name + " "; texMats.Add(string.Format(" {0,-22} x{1,-3} sh={2,-42} {3}", m.name, kv.Value, m.shader != null ? m.shader.name : "?", tex.Length > 0 ? tex : "<단색>")); } var lights = UnityEngine.Object.FindObjectsByType( UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); var cams = UnityEngine.Object.FindObjectsByType( UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); var vols = UnityEngine.Object.FindObjectsByType( UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); sb.AppendLine("===== " + label + " ====="); sb.AppendLine(string.Format(" 렌더러 {0} (Mesh {1} / Skinned {2} / Particle {3}) · 머티리얼 슬롯 {4} · 고유 머티리얼 {5} · 삼각형 {6:N0}", rends.Length, nMeshRend, nSkinned, nPart, slots, mats.Count, tris)); sb.AppendLine(" 셰이더별 슬롯:"); foreach (var kv in shaders) sb.AppendLine(string.Format(" {0,-46} x{1}", kv.Key, kv.Value)); sb.AppendLine(" 머티리얼 전수:"); texMats.Sort(); for (int i = 0; i < texMats.Count; i++) sb.AppendLine(texMats[i]); sb.AppendLine(string.Format(" 라이트 {0}:", lights.Length)); for (int i = 0; i < lights.Length; i++) sb.AppendLine(string.Format(" {0,-18} type={1} color={2} I={3} shadows={4} rot={5} urpData={6}", lights[i].name, lights[i].type, lights[i].color.ToString("F4"), lights[i].intensity, lights[i].shadows, lights[i].transform.rotation.eulerAngles.ToString("F3"), lights[i].GetComponent() != null)); sb.AppendLine(string.Format(" 카메라 {0}:", cams.Length)); for (int i = 0; i < cams.Length; i++) { var c = cams[i]; var acd = c.GetComponent(); sb.AppendLine(string.Format(" {0,-18} ortho={1} size={2} fov={3} near={4} far={5} clear={6} bg={7} pos={8} euler={9} urpData={10} post={11}", c.name, c.orthographic, c.orthographicSize, c.fieldOfView, c.nearClipPlane, c.farClipPlane, c.clearFlags, c.backgroundColor, c.transform.position.ToString("F3"), c.transform.rotation.eulerAngles.ToString("F3"), acd != null, acd != null ? acd.renderPostProcessing.ToString() : "-")); } sb.AppendLine(string.Format(" Volume {0} · Terrain {1}", vols.Length, UnityEngine.Terrain.activeTerrain != null ? UnityEngine.Terrain.activeTerrain.name : "<없음>")); sb.AppendLine(string.Format(" RenderSettings: fog={0} ambMode={1} ambSky={2} ambEq={3} ambGnd={4} ambI={5} skybox={6} reflMode={7} reflI={8} sun={9}", UnityEngine.RenderSettings.fog, UnityEngine.RenderSettings.ambientMode, UnityEngine.RenderSettings.ambientSkyColor, UnityEngine.RenderSettings.ambientEquatorColor, UnityEngine.RenderSettings.ambientGroundColor, UnityEngine.RenderSettings.ambientIntensity, UnityEngine.RenderSettings.skybox != null ? UnityEngine.RenderSettings.skybox.name : "<없음>", UnityEngine.RenderSettings.defaultReflectionMode, UnityEngine.RenderSettings.reflectionIntensity, UnityEngine.RenderSettings.sun != null ? UnityEngine.RenderSettings.sun.name : "<없음>")); } public const string Dir = "Screenshots_WL/WL816a/"; public static void ShotLevel01() { UnityEditor.SceneManagement.EditorSceneManager.OpenScene( "Assets/FarmingIsland/Scenes/Level01.unity", UnityEditor.SceneManagement.OpenSceneMode.Single); Shot(Dir + "a_orig_level01.png", "MainCamera", 1080, 1920); } public static void ShotDemo() { UnityEditor.SceneManagement.EditorSceneManager.OpenScene( "Assets/3DPixelArtEnvironment/Demo/Demo.unity", UnityEditor.SceneManagement.OpenSceneMode.Single); Shot(Dir + "x_demo.png", "Main Camera", 1080, 1920); } // ── 에디트 모드 오프스크린 캡처 (UI 캔버스가 안 끼어든다) ─────────── /// 현재 열린 씬의 카메라로 오프스크린 렌더 → PNG. 인자: 저장경로, 카메라이름(비우면 첫 카메라), w, h public static void Shot(string savePath, string camName, int w, int h) { var cams = UnityEngine.Object.FindObjectsByType( UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); UnityEngine.Camera cam = null; for (int i = 0; i < cams.Length; i++) if (string.IsNullOrEmpty(camName) || cams[i].name == camName) { cam = cams[i]; break; } if (cam == null) { UnityEngine.Debug.Log("[WL816a] 카메라 없음"); return; } ShotFrom(cam, savePath, w, h); } public static void ShotFrom(UnityEngine.Camera cam, string savePath, int w, int h) { var rt = new UnityEngine.RenderTexture(w, h, 24, UnityEngine.RenderTextureFormat.ARGB32, UnityEngine.RenderTextureReadWrite.sRGB); rt.antiAliasing = 1; var prevT = cam.targetTexture; var prevA = UnityEngine.RenderTexture.active; cam.targetTexture = rt; cam.Render(); UnityEngine.RenderTexture.active = rt; var tex = new UnityEngine.Texture2D(w, h, UnityEngine.TextureFormat.RGB24, false); tex.ReadPixels(new UnityEngine.Rect(0, 0, w, h), 0, 0); tex.Apply(); UnityEngine.RenderTexture.active = prevA; cam.targetTexture = prevT; var bytes = UnityEngine.ImageConversion.EncodeToPNG(tex); var dir = System.IO.Path.GetDirectoryName(savePath); if (!System.IO.Directory.Exists(dir)) System.IO.Directory.CreateDirectory(dir); System.IO.File.WriteAllBytes(savePath, bytes); UnityEngine.Object.DestroyImmediate(tex); UnityEngine.Object.DestroyImmediate(rt); UnityEngine.Debug.Log("[WL816a] 캡처 " + savePath + " (" + w + "x" + h + ")"); } }