// WL-816h — ① 지금 상태 실측 (PD 실행 경로 · 하늘 · 물) // PD 경로 재현 = InGame 을 활성 씬으로 Play → Level01 을 Additive (816f 와 같은 호출) // 로그인은 워커 금지(§9)라 못 탄다 → 구조만 같게. using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; public static class WL816h_Probe { public const string Dir = "Screenshots_WL/WL816h/"; public const int W = 1080, H = 1920; public static void Open() { UnityEditor.SceneManagement.EditorSceneManager.OpenScene( "Assets/Scenes/InGame.unity", UnityEditor.SceneManagement.OpenSceneMode.Single); Debug.Log("[816h] InGame 열림"); } public static void Start() { var go = GameObject.Find("~WL816hProbe"); if (go != null) Object.DestroyImmediate(go); go = new GameObject("~WL816hProbe"); go.AddComponent(); Debug.Log("[816h] 러너 시작"); } // ── 에디트 모드: 레퍼런스(아레나·데모) 씬의 하늘을 그대로 읽고 찍는다 ── public static void RefScenes() { var sb = new System.Text.StringBuilder(); Ref(sb, "Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity", "arena"); Ref(sb, "Assets/LowPolyFantasyArena/Scenes/LowPolyArena_Demo.unity", "demo"); System.IO.File.WriteAllText("AgentScripts/WL816h_REF.txt", sb.ToString()); Debug.Log("[816h ref]\n" + sb); } static void Ref(System.Text.StringBuilder sb, string path, string tag) { UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path, UnityEditor.SceneManagement.OpenSceneMode.Single); sb.AppendLine("### " + tag + " " + path); sb.AppendLine(WL816h_Util.SkyLine()); var cams = Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); foreach (var c in cams) { var ac = c.GetComponent(); sb.AppendLine(" CAM " + c.name + " active=" + c.gameObject.activeInHierarchy + " en=" + c.enabled + " ortho=" + c.orthographic + (c.orthographic ? (" size=" + c.orthographicSize) : (" fov=" + c.fieldOfView)) + " clear=" + c.clearFlags + " post=" + (ac == null ? "noACD" : ac.renderPostProcessing.ToString())); } var vols = Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); sb.AppendLine(" Volume 수 = " + vols.Length); // 하늘만 보이는 카메라로 찍는다(수평선 위) var cam = WL816h_Util.SkyCam(); sb.AppendLine(" 하늘 화면색 = " + WL816h_Util.Shot(cam, Dir + "ref_sky_" + tag + ".png", true)); Object.DestroyImmediate(cam.gameObject); } } public static class WL816h_Util { public static string SkyLine() { return "RenderSettings: amb=" + RenderSettings.ambientMode + " light=" + F(RenderSettings.ambientLight) + " sky=" + F(RenderSettings.ambientSkyColor) + " I=" + RenderSettings.ambientIntensity + " skybox=" + (RenderSettings.skybox ? RenderSettings.skybox.name + "/" + RenderSettings.skybox.shader.name : "없음") + " fog=" + RenderSettings.fog + " refl=" + RenderSettings.defaultReflectionMode + "/" + RenderSettings.reflectionIntensity + " sun=" + (RenderSettings.sun ? RenderSettings.sun.name : "없음"); } public static string F(Color c) { return "(" + c.r.ToString("F3") + "," + c.g.ToString("F3") + "," + c.b.ToString("F3") + ")"; } /// 수평선 위만 잡는 카메라 — 화면의 대부분이 하늘이다. public static Camera SkyCam() { var go = new GameObject("~WL816hSkyCam"); go.hideFlags = HideFlags.DontSave; var c = go.AddComponent(); c.orthographic = false; c.fieldOfView = 50f; c.nearClipPlane = 0.3f; c.farClipPlane = 2000f; c.clearFlags = CameraClearFlags.Skybox; c.cullingMask = ~0; c.depth = -100f; go.transform.position = new Vector3(0f, 40f, 0f); go.transform.rotation = Quaternion.Euler(-16f, 30f, 0f); // 위를 본다 = 하늘만 if (go.GetComponent() == null) go.AddComponent(); return c; } /// 오프스크린 렌더 → PNG. 반환 = 화면 평균색(#RRGGBB). public static string Shot(Camera cam, string path, bool wantAvg) { if (cam == null) return "카메라 없음"; System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path)); var rt = new RenderTexture(WL816h_Probe.W, WL816h_Probe.H, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB); rt.antiAliasing = 1; rt.Create(); var prevT = cam.targetTexture; var prevA = RenderTexture.active; cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt; var tex = new Texture2D(WL816h_Probe.W, WL816h_Probe.H, TextureFormat.RGB24, false); tex.ReadPixels(new Rect(0, 0, WL816h_Probe.W, WL816h_Probe.H), 0, 0); tex.Apply(); RenderTexture.active = prevA; cam.targetTexture = prevT; System.IO.File.WriteAllBytes(path, tex.EncodeToPNG()); string avg = ""; if (wantAvg) { var px = tex.GetPixels32(); long r = 0, g = 0, b = 0; for (int i = 0; i < px.Length; i++) { r += px[i].r; g += px[i].g; b += px[i].b; } avg = "#" + ((int)(r / px.Length)).ToString("X2") + ((int)(g / px.Length)).ToString("X2") + ((int)(b / px.Length)).ToString("X2"); } Object.DestroyImmediate(tex); rt.Release(); Object.DestroyImmediate(rt); return avg + " → " + path; } } public class WL816h_ProbeRunner : MonoBehaviour { static System.Text.StringBuilder sb; void Start() { StartCoroutine(Co()); } static void L(string s) { sb.AppendLine(s); } IEnumerator Co() { sb = new System.Text.StringBuilder(); L("=== WL-816h 지금 상태 (PD 경로 = InGame 활성 + Level01 Additive) ==="); L("t0 활성씬=" + SceneManager.GetActiveScene().name + " / " + WL816h_Util.SkyLine()); bool viaGame = false; try { if (InGameInfo.Ins != null) { InGameInfo.Ins.Load_Map(900); viaGame = true; } } catch (System.Exception e) { L("Load_Map 예외(=로그인 없이는 못 탄다): " + e.GetType().Name); } if (!viaGame) { L("→ SceneInfo.Load_AddScene 과 같은 호출로 대체: LoadSceneAsync(\"Level01\", Additive)"); var op = SceneManager.LoadSceneAsync("Level01", LoadSceneMode.Additive); while (op != null && !op.isDone) yield return null; } for (int i = 0; i < 6; i++) yield return new WaitForSeconds(1f); L(""); L("t+6s 활성씬=" + SceneManager.GetActiveScene().name + " sceneCount=" + SceneManager.sceneCount); L("🔴 " + WL816h_Util.SkyLine()); L("IslandLook: 렌더러 " + WL.Look.Farm.WLIslandLook.SwappedRenderers + " light=" + WL.Look.Farm.WLIslandLook.LightingApplied + " refLook=" + WL.Look.Farm.WLIslandLook.ReferenceLookApplied); L("RefLook : applied=" + WL.Look.Arena.WLReferenceLook.IsApplied + " log=" + WL.Look.Arena.WLReferenceLook.LastLog); // ── 🔴 카메라 · 포스트 — 아레나 무드가 「보이는 카메라」에 실제로 걸렸나 ── L(""); Camera live = null; var cams = Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); foreach (var c in cams) { bool isLive = c.gameObject.activeInHierarchy && c.enabled && c.targetTexture == null; var ac = c.GetComponent(); L("CAM " + c.name + " scene=" + c.gameObject.scene.name + " live=" + isLive + " depth=" + c.depth + " tag=" + c.tag + " clear=" + c.clearFlags + " 🔴post=" + (ac == null ? "noACD" : ac.renderPostProcessing.ToString())); if (isLive && (live == null || c.depth > live.depth)) live = c; } L("→ 보이는 카메라 = " + (live == null ? "없음" : live.name + "(" + live.gameObject.scene.name + ")")); L("Camera.main = " + (Camera.main == null ? "없음" : Camera.main.name + "(" + Camera.main.gameObject.scene.name + ")")); var vols = Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); foreach (var v in vols) L("Volume " + v.name + " global=" + v.isGlobal + " w=" + v.weight + " prio=" + v.priority + " profile=" + (v.sharedProfile ? v.sharedProfile.name : "없음")); // ── 물 ── L(""); foreach (var r in Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None)) { if (r == null || r.gameObject.scene.name != "Level01") continue; var m = r.sharedMaterial; if (m == null || m.shader == null) continue; if (!m.shader.name.ToLower().Contains("water") && !r.name.ToLower().Contains("water")) continue; L("WATER obj=" + r.name + " layer=" + r.gameObject.layer + " mat=" + m.name + " shader=" + m.shader.name + " queue=" + m.renderQueue + " bounds=" + r.bounds.size.ToString("F0") + " pos=" + r.transform.position.ToString("F1")); } // ── URP 렌더러가 Opaque/Depth 텍스처를 주나(ToonWaterU 가 요구) ── var urp = GraphicsSettings.defaultRenderPipeline as UniversalRenderPipelineAsset; L("URP asset = " + (urp == null ? "없음" : urp.name + " opaqueTex=" + urp.supportsCameraOpaqueTexture + " depthTex=" + urp.supportsCameraDepthTexture + " msaa=" + urp.msaaSampleCount)); // ── 캡처 ── L(""); L("하늘(섬) = " + WL816h_Util.Shot(WL816h_Util.SkyCam(), WL816h_Probe.Dir + "a_now_sky.png", true)); L("섬 화면 = " + WL816h_Util.Shot(live, WL816h_Probe.Dir + "a_now_island.png", true)); L("물 근접 = " + WL816h_Util.Shot(WaterCam(), WL816h_Probe.Dir + "a_now_water.png", true)); System.IO.File.WriteAllText("AgentScripts/WL816h_PROBE.txt", sb.ToString()); Debug.Log("[816h probe 완료]\n" + sb); } /// 물이 화면의 절반을 차지하는 카메라(섬 가장자리 바깥). public static Camera WaterCam() { var go = GameObject.Find("~WL816hWaterCam"); if (go == null) { go = new GameObject("~WL816hWaterCam"); go.hideFlags = HideFlags.DontSave; } var c = go.GetComponent(); if (c == null) c = go.AddComponent(); c.orthographic = false; c.fieldOfView = 45f; c.nearClipPlane = 0.3f; c.farClipPlane = 2000f; c.clearFlags = CameraClearFlags.Skybox; c.cullingMask = ~0; c.depth = -100f; go.transform.position = new Vector3(-18f, 6f, -18f); go.transform.rotation = Quaternion.Euler(12f, 45f, 0f); if (go.GetComponent() == null) go.AddComponent(); return c; } }