// WL-816j — ① 실측: 물 평면의 실제 크기 · 셰이더 무늬 속성 전수 · 무늬 1칸이 몇 m 인가 // 에디트 모드 · 씬 저장 0 · 에셋 수정 0 (읽기만). using System.Text; using UnityEngine; using UnityEditor; using UnityEditor.SceneManagement; public static class WL816j_Probe { const string MatDir = "Assets/WL/Look/Farm/Materials/"; const string Voronoi = "Assets/ResWork/UToonAndRealisticWater/Textures/Default/VoronoiVer2.png"; // 셰이더 속성 = 사람 이름 → 레퍼런스 이름 (ToonWaterU.shadergraph 실측) public static readonly string[,] P = { {"Size","Vector1_07238257334b4a149e675e2451801030"}, {"Speed","Vector1_8e22a98f75c94b218c49e6c4805e799d"}, {"Strength","Vector1_99cc56b5c6fd474082f07f00a6df94f9"}, {"NoiseSpeed","Vector1_ad7e0fcd37f44d68b68de6f06bb43b96"}, {"FoamScale","Vector1_11671d7a4cdb4d059a6c69e39f3f7b3f"}, {"FoamSpeed","Vector1_3089b6a325a44c1686907af4ee3b0776"}, {"FoamDistance","Vector1_101dc4546b684d40bc2ff2fc59ab43d5"}, {"FoamEdge","Vector1_34f757bec6b8422b9aef3b9d97117a6e"}, {"DeepDistance","Vector1_566e288f42864b8e9432d81fbdb83f38"}, {"Height","Vector1_d813b569a4d541d1b2ac4ea9bc66a3b9"}, {"WaweSpeed","Vector1_ff7a2780aaa94ddd86e156c4707e39a2"}, {"WaweNormalSize","Vector1_68f0c21b684f4b7c9ebef8789113b107"}, {"WaweNormalSpeed","Vector1_85ea9246e72a44ed9e0482861767c826"}, {"WaweNormalStrength","Vector1_2b4963cef1de4859983ffcbae94c6f60"}, {"Smoothness","Vector1_21ae4fce4585460386edec89c9895501"}, {"Metallic","Vector1_dd1e17693dc14b10b91828bdfd5adaa8"}, {"AlphaValue","Vector1_7090c8ca8ea84e2d85858ae4beb5be38"}, }; public static string Ref(string human) { for (int i = 0; i < P.GetLength(0); i++) if (P[i, 0] == human) return P[i, 1]; return null; } public static void Run() { var sb = new StringBuilder(); sb.AppendLine("=== WL-816j 실측 ① 물 평면 · 무늬 크기 ==="); // ── 물 평면 ──────────────────────────────────────────────── var scn = EditorSceneManager.OpenScene("Assets/FarmingIsland/Scenes/Level01.unity", OpenSceneMode.Additive); Renderer water = null; foreach (var r in Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None)) if (r != null && r.gameObject.scene == scn && r.name == "Water") water = r; float planeW = 0f; if (water == null) sb.AppendLine("🔴 Water 렌더러 없음"); else { var mf = water.GetComponent(); var m = mf != null ? mf.sharedMesh : null; var t = water.transform; sb.AppendLine("물 오브젝트 = " + water.name + " pos=" + t.position + " lossyScale=" + t.lossyScale); sb.AppendLine(" mat=" + (water.sharedMaterial ? water.sharedMaterial.name : "?") + " shader=" + (water.sharedMaterial && water.sharedMaterial.shader ? water.sharedMaterial.shader.name : "?")); if (m != null) { var b = m.bounds; planeW = b.size.x * t.lossyScale.x; sb.AppendLine(" mesh=" + m.name + " verts=" + m.vertexCount + " tris=" + (m.triangles.Length / 3) + " 로컬크기=" + b.size + " → 월드 " + planeW.ToString("F0") + " × " + (b.size.z * t.lossyScale.z).ToString("F0") + " m"); var uv = m.uv; float u0 = 9f, u1 = -9f, v0 = 9f, v1 = -9f; for (int i = 0; i < uv.Length; i++) { u0 = Mathf.Min(u0, uv[i].x); u1 = Mathf.Max(u1, uv[i].x); v0 = Mathf.Min(v0, uv[i].y); v1 = Mathf.Max(v1, uv[i].y); } sb.AppendLine(" UV0 범위 = u[" + u0.ToString("F2") + "," + u1.ToString("F2") + "] v[" + v0.ToString("F2") + "," + v1.ToString("F2") + "]" + " → UV 1칸 = 월드 " + (planeW / Mathf.Max(0.0001f, u1 - u0)).ToString("F1") + " m"); // 정점 간격 = 버텍스 파도가 표현 가능한 최소 파장 int side = Mathf.RoundToInt(Mathf.Sqrt(m.vertexCount)); sb.AppendLine(" 🔴 정점 간격 = " + (planeW / Mathf.Max(1, side - 1)).ToString("F1") + " m (" + side + "×" + side + " 격자) → 버텍스 파도(파장 4.4 m)는 표현 불가"); } sb.AppendLine(" bounds(월드) = " + water.bounds.size); } // ── 섬 타일 · 기준 크기 ──────────────────────────────────── Bounds land = new Bounds(); bool first = true; int landN = 0; foreach (var r in Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None)) { if (r == null || r.gameObject.scene != scn || r == water) continue; if (r.bounds.size.sqrMagnitude <= 0f) continue; if (first) { land = r.bounds; first = false; } else land.Encapsulate(r.bounds); landN++; } sb.AppendLine("섬(물 제외) 렌더러 " + landN + "개 · 월드 bounds size=" + land.size + " center=" + land.center); sb.AppendLine("기준: 캐릭터 키 1.19 m · 섬 타일 8 m"); // ── 머티리얼 값 전수 ─────────────────────────────────────── string[] mats = { "Farm_Water_WL_C" }; foreach (var mn in mats) { var mm = AssetDatabase.LoadAssetAtPath(MatDir + mn + ".mat"); if (mm == null) { sb.AppendLine("🔴 " + mn + " 없음"); continue; } sb.AppendLine(""); sb.AppendLine("[" + mn + "] 무늬 관련 속성 전수"); for (int i = 0; i < P.GetLength(0); i++) sb.AppendLine(" " + P[i, 0].PadRight(20) + " = " + mm.GetFloat(P[i, 1]).ToString("G6")); } // ── 무늬 1칸이 몇 m 인가 (보로노이 텍스처 = 한 타일에 6칸 · 파이썬 실측) ── var tex = AssetDatabase.LoadAssetAtPath(Voronoi); sb.AppendLine(""); sb.AppendLine("보로노이 텍스처 = " + (tex ? tex.name + " " + tex.width + "×" + tex.height + " mip=" + tex.mipmapCount + " wrap=" + tex.wrapMode : "없음")); const float N = 6f; // 한 타일에 들어 있는 보로노이 칸 수(가로) — 실측 var cur = AssetDatabase.LoadAssetAtPath(MatDir + "Farm_Water_WL_C.mat"); if (cur != null && planeW > 0f) { float size = cur.GetFloat(Ref("Size")); float foamScale = cur.GetFloat(Ref("FoamScale")); float noiseSpeed = cur.GetFloat(Ref("NoiseSpeed")); sb.AppendLine("🔴 지금 무늬 1칸 = 평면 " + planeW.ToString("F0") + " m ÷ (Size " + size + " × 칸 " + N + ") = " + (planeW / (size * N)).ToString("F1") + " m (섬 타일 8 m · 캐릭터 1.19 m)"); sb.AppendLine("🔴 지금 거품 노이즈 1칸 = " + planeW.ToString("F0") + " m ÷ FoamScale " + foamScale + " = " + (planeW / foamScale).ToString("F1") + " m"); sb.AppendLine(" 무늬 흐르는 속도 = NoiseSpeed " + noiseSpeed + " 타일/s × 타일 " + (planeW / size).ToString("F1") + " m = " + (noiseSpeed * planeW / size).ToString("F2") + " m/s"); sb.AppendLine(" → 목표 1칸 1 m 이면 Size = " + (planeW / (1f * N)).ToString("F0") + " · 2 m 이면 " + (planeW / (2f * N)).ToString("F0") + " · 3 m 이면 " + (planeW / (3f * N)).ToString("F0")); } sb.AppendLine("참고(벤더 데모 실측) UToonAndRealisticShaderSampleScene 의 Water = 기본 Plane scale 1 = 10 m · ToonWater.mat Size 2 → 타일 5 m · 1칸 0.83 m · FoamScale 50 → 거품칸 0.2 m"); EditorSceneManager.CloseScene(scn, true); System.IO.Directory.CreateDirectory("AgentScripts"); System.IO.File.WriteAllText("AgentScripts/WL816j_PROBE.txt", sb.ToString()); Debug.Log("[816j probe]\n" + sb); } }