// WL-816f — ① PD 실행 경로 재현 (로그인 없이): InGame 씬 Play → Level01 을 Additive 로 붙인다. // = InGameInfo.Load_Map(900) → SceneInfo.Load_AddScene 이 하는 것과 같은 구조(활성 씬 = InGame). // 배치모드 헤드리스에서 동작. 캡처는 오프스크린 렌더. public static class WL816f_Pd { public const string Dir = "Screenshots_WL/WL816f/"; public const int W = 1080, H = 1920; public static string Report = ""; // ── 에디트 모드: 씬 준비 ─────────────────────────────────────────── public static void Open() { UnityEditor.SceneManagement.EditorSceneManager.OpenScene( "Assets/Scenes/InGame.unity", UnityEditor.SceneManagement.OpenSceneMode.Single); UnityEngine.Debug.Log("[816f] InGame 열림 dirty=" + UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().isDirty); } // ── Play 중: 러너를 띄운다 ───────────────────────────────────────── public static void Start() { var go = UnityEngine.GameObject.Find("~WL816fPd"); if (go != null) UnityEngine.Object.DestroyImmediate(go); go = new UnityEngine.GameObject("~WL816fPd"); go.AddComponent(); UnityEngine.Debug.Log("[816f] 러너 시작"); } public static void Fetch() { var txt = WL816f_PdRunner.Log; System.IO.File.WriteAllText("AgentScripts/WL816f_PD.txt", txt); UnityEngine.Debug.Log("[816f]\n" + txt); } } public class WL816f_PdRunner : UnityEngine.MonoBehaviour { public static string Log = "(아직)"; static System.Text.StringBuilder sb; void Start() { StartCoroutine(Co()); } System.Collections.IEnumerator Co() { sb = new System.Text.StringBuilder(); L("=== PD 경로 재현 (InGame 활성 + Level01 Additive) ==="); L("t0 활성씬=" + UnityEngine.SceneManagement.SceneManager.GetActiveScene().name + " sceneCount=" + UnityEngine.SceneManagement.SceneManager.sceneCount); // 훅 설치 상태 var cfg = WL.Look.Farm.WLIslandLookSettings.Instance; L("SO enabled_=" + (cfg == null ? -1 : cfg.enabled_) + " applyLook=" + (cfg == null ? -1 : cfg.applyLook) + " grass=" + (cfg == null ? -1 : cfg.grassEnabled)); // InGameInfo 로 진짜 경로를 태워 본다 bool viaGame = false; try { if (InGameInfo.Ins != null) { L("InGameInfo.Ins 있음 → Load_Map(900) 시도"); InGameInfo.Ins.Load_Map(900); viaGame = true; } } catch (System.Exception e) { L("Load_Map 예외: " + e.GetType().Name + " " + e.Message); } if (!viaGame) { L("→ 로그인 없이는 Load_Map 이 못 돈다. SceneInfo.Load_AddScene 과 **같은 호출**로 대체:"); L(" SceneManager.LoadSceneAsync(\"Level01\", Additive)"); var op = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("Level01", UnityEngine.SceneManagement.LoadSceneMode.Additive); while (op != null && !op.isDone) yield return null; } for (int i = 0; i < 6; i++) yield return new UnityEngine.WaitForSeconds(1f); L(""); L("t+6s 활성씬=" + UnityEngine.SceneManagement.SceneManager.GetActiveScene().name + " sceneCount=" + UnityEngine.SceneManagement.SceneManager.sceneCount); for (int i = 0; i < UnityEngine.SceneManagement.SceneManager.sceneCount; i++) { var s = UnityEngine.SceneManagement.SceneManager.GetSceneAt(i); L(" scene[" + i + "] " + s.name + " loaded=" + s.isLoaded + " roots=" + (s.isLoaded ? s.rootCount : -1)); } // ── 훅이 돌았나 ─────────────────────────────────────────────── L(""); L("IslandLook : 렌더러 " + WL.Look.Farm.WLIslandLook.SwappedRenderers + " 슬롯 " + WL.Look.Farm.WLIslandLook.SwappedSlots + " look=" + WL.Look.Farm.WLIslandLook.LookApplied + " light=" + WL.Look.Farm.WLIslandLook.LightingApplied + " refLook=" + WL.Look.Farm.WLIslandLook.ReferenceLookApplied + " grassSpawned=" + WL.Look.Farm.WLIslandLook.GrassSpawned); L("Grass : " + WL.Look.Farm.WLIslandGrass.LastLog); var g = UnityEngine.Object.FindFirstObjectByType(UnityEngine.FindObjectsInactive.Include); L("GrassObj : " + (g == null ? "없음" : (g.name + " active=" + g.gameObject.activeInHierarchy + "/" + g.enabled + " scene=" + g.gameObject.scene.name + " layer=" + g.gameObject.layer))); L("RefLook : applied=" + WL.Look.Arena.WLReferenceLook.IsApplied + " outlined=" + WL.Look.Arena.WLReferenceLook.OutlinedRenderers); L("ambient : " + UnityEngine.RenderSettings.ambientMode + " " + UnityEngine.RenderSettings.ambientLight + " skybox=" + (UnityEngine.RenderSettings.skybox ? UnityEngine.RenderSettings.skybox.name : "없음") + " fog=" + UnityEngine.RenderSettings.fog); // ── 카메라 — 누가 실제로 화면을 그리나 ──────────────────────── L(""); var cams = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None); UnityEngine.Camera top = null; for (int i = 0; i < cams.Length; i++) { var c = cams[i]; bool live = c.gameObject.activeInHierarchy && c.enabled && c.targetTexture == null; L("CAM " + c.name + " scene=" + c.gameObject.scene.name + " live=" + live + " depth=" + c.depth + " mask=0x" + c.cullingMask.ToString("X") + " clear=" + c.clearFlags + " pos=" + c.transform.position.ToString("F1")); if (live && (top == null || c.depth > top.depth)) top = c; } L("→ 화면에 보이는 카메라 = " + (top == null ? "없음" : top.name + " (scene " + top.gameObject.scene.name + ")")); if (top != null) { L(" 그 카메라의 컬링마스크에 들어가는 레이어:"); string inc = "", exc = ""; for (int i = 0; i < 32; i++) { string n = UnityEngine.LayerMask.LayerToName(i); if (string.IsNullOrEmpty(n)) continue; if ((top.cullingMask & (1 << i)) != 0) inc += i + ":" + n + " "; else exc += i + ":" + n + " "; } L(" 포함 = " + inc); L(" 🔴제외 = " + exc); } // ── 섬 렌더러가 어느 레이어에 있나 ──────────────────────────── L(""); var counts = new System.Collections.Generic.Dictionary(); var rends = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); int nIsland = 0; for (int i = 0; i < rends.Length; i++) { if (rends[i].gameObject.scene.name != "Level01") continue; nIsland++; int l = rends[i].gameObject.layer; counts[l] = counts.ContainsKey(l) ? counts[l] + 1 : 1; } L("Level01 렌더러 " + nIsland + " 개의 레이어 분포:"); foreach (var kv in counts) L(" layer " + kv.Key + " (" + UnityEngine.LayerMask.LayerToName(kv.Key) + ") = " + kv.Value + (top != null ? ((top.cullingMask & (1 << kv.Key)) != 0 ? " [보임]" : " 🔴[안 보임]") : "")); L("풀이 그려지는 레이어 = " + UnityEngine.LayerMask.NameToLayer("Default") + " (InstancesBehaviour.Update 고정)"); L("Soil 톤 : farm " + WL.Look.Farm.WLIslandLook.SoilFarmsToned + " · 타일 " + WL.Look.Farm.WLIslandLook.SoilTilesRepainted); // ── 캡처 (보이는 카메라 그대로 + 위에서 + 표준 바닥 카메라) ── Shot(top, WL816f_Pd.Dir + "a_pd_path.png"); Shot(TopCam(), WL816f_Pd.Dir + "a_pd_path_top.png"); Shot(GroundCam(CleanSpot(), 6f), WL816f_Pd.Dir + "x_ours_ground.png"); Shot(GroundCam(CleanSpot(), 10f), WL816f_Pd.Dir + "x_ours_wide.png"); Log = sb.ToString(); System.IO.File.WriteAllText("AgentScripts/WL816f_PD.txt", Log); UnityEngine.Debug.Log("[816f 완료]\n" + Log); } static void L(string s) { sb.AppendLine(s); } /// 소품이 가장 적은(=풀이 가장 넓은) 섬 타일의 중심. UnityEngine.Vector3 CleanSpot() { var islands = UnityEngine.Object.FindObjectsByType( UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); UnityEngine.Vector3 best = UnityEngine.Vector3.zero; int bs = int.MaxValue; for (int i = 0; i < islands.Length; i++) { var isl = islands[i]; if (isl == null || !isl.IsUnlocked || !isl.gameObject.activeInHierarchy) continue; int sc = isl.GetComponentsInChildren(false).Length; if (sc < bs) { bs = sc; best = isl.transform.position; } } return best; } /// 표준 바닥 카메라 — 데모와 같은 화각(직교 · euler 30,60,0). public static UnityEngine.Camera GroundCam(UnityEngine.Vector3 spot, float size) { var go = UnityEngine.GameObject.Find("~WL816fGroundCam"); if (go == null) { go = new UnityEngine.GameObject("~WL816fGroundCam"); go.hideFlags = UnityEngine.HideFlags.DontSave; } var c = go.GetComponent(); if (c == null) c = go.AddComponent(); c.orthographic = true; c.orthographicSize = size; c.nearClipPlane = 0.3f; c.farClipPlane = 500f; c.clearFlags = UnityEngine.CameraClearFlags.SolidColor; c.backgroundColor = new UnityEngine.Color(0.192f, 0.302f, 0.475f, 1f); c.cullingMask = ~0; c.depth = -100f; var rot = UnityEngine.Quaternion.Euler(30f, 60f, 0f); go.transform.rotation = rot; go.transform.position = spot - rot * UnityEngine.Vector3.forward * 60f; if (go.GetComponent() == null) go.AddComponent(); return c; } UnityEngine.Camera TopCam() { var go = new UnityEngine.GameObject("~WL816fTop"); var c = go.AddComponent(); c.orthographic = true; c.orthographicSize = 14f; c.nearClipPlane = 0.3f; c.farClipPlane = 500f; c.clearFlags = UnityEngine.CameraClearFlags.Skybox; c.cullingMask = ~0; c.depth = -100f; var rot = UnityEngine.Quaternion.Euler(30f, 60f, 0f); go.transform.rotation = rot; go.transform.position = new UnityEngine.Vector3(0f, 1f, 0f) - rot * UnityEngine.Vector3.forward * 60f; if (go.GetComponent() == null) go.AddComponent(); return c; } public static void Shot(UnityEngine.Camera cam, string path) { if (cam == null) { L("캡처 실패(카메라 없음) " + path); return; } System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path)); var rt = new UnityEngine.RenderTexture(WL816f_Pd.W, WL816f_Pd.H, 24, UnityEngine.RenderTextureFormat.ARGB32, UnityEngine.RenderTextureReadWrite.sRGB); rt.antiAliasing = 1; rt.Create(); var prevT = cam.targetTexture; var prevA = UnityEngine.RenderTexture.active; cam.targetTexture = rt; cam.Render(); UnityEngine.RenderTexture.active = rt; var tex = new UnityEngine.Texture2D(WL816f_Pd.W, WL816f_Pd.H, UnityEngine.TextureFormat.RGB24, false); tex.ReadPixels(new UnityEngine.Rect(0, 0, WL816f_Pd.W, WL816f_Pd.H), 0, 0); tex.Apply(); System.IO.File.WriteAllBytes(path, UnityEngine.ImageConversion.EncodeToPNG(tex)); UnityEngine.RenderTexture.active = prevA; cam.targetTexture = prevT; UnityEngine.Object.DestroyImmediate(tex); rt.Release(); UnityEngine.Object.DestroyImmediate(rt); if (sb != null) L("캡처 " + path); } }