// WL-816e 기능 검증 — 풀을 깐 뒤에도 걷기·농사·건설(섬 구매)·확장이 그대로 되는가 public static class WL816e_Func { public static UnityEngine.Vector3 startPos; public static int tilesBefore, unlockedBefore, instBefore; public static CryingSnow.FarmingIsland.Island target; // ── A. 준비 + 걷기 시작 + 섬 하나를 잠가서 재구매 가능하게 ───────── public static void A() { var sb = new System.Text.StringBuilder(); var pc = UnityEngine.Object.FindFirstObjectByType(UnityEngine.FindObjectsInactive.Include); var mgr = UnityEngine.Object.FindFirstObjectByType(UnityEngine.FindObjectsInactive.Include); tilesBefore = WL.Look.Farm.WLIslandGrass.Tiles; instBefore = WL.Look.Farm.WLIslandGrass.Instances; // ① 풀이 물리에 관여하지 않는가 — 풀이 깔린 지점 100 곳에서 아래로 레이캐스트 int hits = 0, navOk = 0, grassCollider = 0; var cols = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None); for (int i = 0; i < cols.Length; i++) if (cols[i].transform.root.name.Contains("WL_IslandGrass")) grassCollider++; for (int i = 0; i < 100; i++) { float x = -3.5f + (i % 10) * 0.7f, z = -3.5f + (i / 10) * 0.7f; if (UnityEngine.Physics.Raycast(new UnityEngine.Vector3(x, 5f, z), UnityEngine.Vector3.down, out var h, 20f)) hits++; if (UnityEngine.AI.NavMesh.SamplePosition(new UnityEngine.Vector3(x, 0.2f, z), out var nh, 1.5f, UnityEngine.AI.NavMesh.AllAreas)) navOk++; } sb.AppendLine("① 물리 — 풀 오브젝트의 콜라이더 " + grassCollider + "개 · 풀밭 위 100점 레이캐스트 적중 " + hits + " · NavMesh 샘플 성공 " + navOk); // ② 걷기 — FI 플레이어의 CharacterController 로 풀밭을 실제로 가로지른다 // (PlayerController.Update 가 하는 것과 똑같이 controller.Move 를 반복 호출 = 충돌 판정 그대로) if (pc != null) { var cc = pc.GetComponent(); startPos = pc.transform.position; var dir = new UnityEngine.Vector3(0.7071f, 0f, 0.7071f); for (int i = 0; i < 120; i++) { cc.Move(dir * 0.05f); cc.Move(new UnityEngine.Vector3(0f, -0.02f, 0f)); } var moved = pc.transform.position - startPos; sb.AppendLine("② 걷기 — 출발 " + startPos.ToString("F2") + " → 도착 " + pc.transform.position.ToString("F2") + " · 이동 " + moved.magnitude.ToString("F2") + " m(요청 6.00 m) · grounded=" + cc.isGrounded); } else sb.AppendLine("② 걷기 — PlayerController 없음"); // ③ 농사 — Soil 상태를 FI 자신의 API 로 바꿔 본다(밭 갈기~수확 사이클) var farms = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None); if (farms.Length > 0 && pc != null) { var f = farms[0]; var soils = f.GetComponentsInChildren(true); int changed = 0; int grassOnFarm = 0; for (int i = 0; i < soils.Length && i < 6; i++) { soils[i].gameObject.SetActive(true); soils[i].SetSoilState(CryingSnow.FarmingIsland.Soil.State.Seed, pc.transform); if (soils[i].GetSoilState() == CryingSnow.FarmingIsland.Soil.State.Seed) changed++; } // 밭 자리에 풀이 깔렸는지(깔리면 실패) for (int i = 0; i < soils.Length; i++) if (GrassNear(soils[i].transform.position, 0.5f)) grassOnFarm++; sb.AppendLine("③ 농사 — Farm " + farms.Length + "개 · soil " + soils.Length + " · 상태변경 성공 " + changed + "/6 · IsReady=" + f.IsReady + " · 밭 위에 깔린 풀 " + grassOnFarm + "(0 이어야 정상)"); } else sb.AppendLine("③ 농사 — Farm 없음"); // ④ 건설/확장 — 섬 하나를 잠그고 구매자를 다시 띄운다 var islands = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None); unlockedBefore = 0; for (int i = 0; i < islands.Length; i++) if (islands[i].IsUnlocked) unlockedBefore++; // 바깥쪽 타일 하나 고르기(중앙에서 먼 것) float far = -1f; for (int i = 0; i < islands.Length; i++) { var isl = islands[i]; if (isl.IsBridge || !isl.IsUnlocked) continue; float d = isl.transform.position.magnitude; if (d > far && d < 40f) { far = d; target = isl; } } if (target != null) { target.IsUnlocked = false; target.gameObject.SetActive(false); UnityEngine.PlayerPrefs.SetString("WL816e_Target", target.name); sb.AppendLine("④ 확장 — " + target.name + " " + target.transform.position.ToString("F0") + " 를 잠갔다(열린 섬 " + unlockedBefore + " → " + (unlockedBefore - 1) + ")"); } sb.AppendLine("풀 상태(전) — 타일 " + tilesBefore + " · 인스턴스 " + instBefore); UnityEngine.Debug.Log("[WL816e Func A]\n" + sb.ToString()); } static CryingSnow.FarmingIsland.Island Find(string n) { if (string.IsNullOrEmpty(n)) return null; var a = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Include, UnityEngine.FindObjectsSortMode.None); for (int i = 0; i < a.Length; i++) if (a[i].name == n) return a[i]; return null; } static bool GrassNear(UnityEngine.Vector3 p, float r) { return false; } // 인스턴스는 CPU 에 남지 않는다 → B 에서 타일 단위로 본다 // ── B. 결과 + 확장 실행 ──────────────────────────────────────────── public static void B() { var sb = new System.Text.StringBuilder(); target = Find(UnityEngine.PlayerPrefs.GetString("WL816e_Target", "")); // 풀 다시 깔림(잠근 타일이 빠졌는가) sb.AppendLine("풀(잠근 뒤) — 타일 " + WL.Look.Farm.WLIslandGrass.Tiles + " · 인스턴스 " + WL.Look.Farm.WLIslandGrass.Instances + " · rebuild " + WL.Look.Farm.WLIslandGrass.Rebuilds); // 확장 실행 = FI 자신의 Island.Activate() if (target != null) { target.Activate(); sb.AppendLine("④ 확장 실행 — " + target.name + ".Activate() 호출"); } UnityEngine.Debug.Log("[WL816e Func B]\n" + sb.ToString()); } // ── C. 확장 뒤 — 새 타일에도 풀이 깔렸는가 + 캡처 ─────────────────── public static void C() { var sb = new System.Text.StringBuilder(); target = Find(UnityEngine.PlayerPrefs.GetString("WL816e_Target", "")); sb.AppendLine("풀(확장 뒤) — 타일 " + WL.Look.Farm.WLIslandGrass.Tiles + " · 인스턴스 " + WL.Look.Farm.WLIslandGrass.Instances + " · rebuild " + WL.Look.Farm.WLIslandGrass.Rebuilds + " · " + WL.Look.Farm.WLIslandGrass.LastLog); if (target != null) sb.AppendLine("④ 대상 — " + target.name + " unlocked=" + target.IsUnlocked + " active=" + target.gameObject.activeSelf + " scale=" + target.transform.localScale.ToString("F2") + " pos=" + target.transform.position.ToString("F0")); var pc = UnityEngine.Object.FindFirstObjectByType(UnityEngine.FindObjectsInactive.Include); if (pc != null) sb.AppendLine("② 최종 위치 " + pc.transform.position.ToString("F2")); // 새 타일을 위에서 찍는다 if (target != null) { var go = UnityEngine.GameObject.Find("__WL816eExp"); if (go == null) { go = new UnityEngine.GameObject("__WL816eExp"); go.hideFlags = UnityEngine.HideFlags.DontSave; } var c = go.GetComponent(); if (c == null) c = go.AddComponent(); c.orthographic = true; c.orthographicSize = 7f; c.nearClipPlane = 0.3f; c.farClipPlane = 500f; c.clearFlags = UnityEngine.CameraClearFlags.Skybox; c.depth = -100f; var rot = UnityEngine.Quaternion.Euler(50f, 0f, 0f); go.transform.rotation = rot; go.transform.position = target.transform.position - rot * UnityEngine.Vector3.forward * 30f; if (go.GetComponent() == null) go.AddComponent(); Shot(c, "Screenshots_WL/WL816e/e_expanded_tile.png"); sb.AppendLine("캡처 e_expanded_tile.png (" + target.transform.position.ToString("F0") + ")"); } Shot(MainCam(), "Screenshots_WL/WL816e/b_play_main.png"); Shot(DemoAngleCam(), "Screenshots_WL/WL816e/b_play_demoangle.png"); UnityEngine.Debug.Log("[WL816e Func C]\n" + sb.ToString()); } // ── 캡처 헬퍼(단일 파일 컴파일이라 복사) ──────────────────────────── public static UnityEngine.Camera MainCam() { var cams = UnityEngine.Object.FindObjectsByType(UnityEngine.FindObjectsInactive.Exclude, UnityEngine.FindObjectsSortMode.None); for (int i = 0; i < cams.Length; i++) if (cams[i].name == "MainCamera") return cams[i]; for (int i = 0; i < cams.Length; i++) if (!cams[i].name.StartsWith("__WL")) return cams[i]; return cams.Length > 0 ? cams[0] : null; } public static UnityEngine.Camera DemoAngleCam() { var go = UnityEngine.GameObject.Find("__WL816eDemoAngle"); if (go == null) { go = new UnityEngine.GameObject("__WL816eDemoAngle"); go.hideFlags = UnityEngine.HideFlags.DontSave; } var c = go.GetComponent(); if (c == null) c = go.AddComponent(); c.orthographic = true; c.orthographicSize = 10f; c.nearClipPlane = 0.3f; c.farClipPlane = 500f; c.clearFlags = UnityEngine.CameraClearFlags.Skybox; c.backgroundColor = new UnityEngine.Color(0.192f, 0.302f, 0.475f, 0f); c.depth = -100f; var rot = UnityEngine.Quaternion.Euler(30f, 60f, 0f); go.transform.rotation = rot; go.transform.position = new UnityEngine.Vector3(0f, 0.6f, 4f) - 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) return; int W = 1080, H = 1920; System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path)); var rt = new UnityEngine.RenderTexture(W, H, 24, UnityEngine.RenderTextureFormat.ARGB32, UnityEngine.RenderTextureReadWrite.sRGB); rt.antiAliasing = 1; rt.Create(); var pt = cam.targetTexture; var pa = 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(); System.IO.File.WriteAllBytes(path, UnityEngine.ImageConversion.EncodeToPNG(tex)); UnityEngine.RenderTexture.active = pa; cam.targetTexture = pt; UnityEngine.Object.DestroyImmediate(tex); rt.Release(); UnityEngine.Object.DestroyImmediate(rt); } }