// WL-814q 마감 — 전투장 바닥이 「흙」으로 읽히게 ToonTerrain 머티리얼 변형 1개를 우리 폴더에 만든다. // 🔴 원본 Assets/3DPixelArtEnvironment/Materials/Terrain.mat 은 건드리지 않는다(복사본 생성). // 되돌리기 = 씬 Terrain 의 materialTemplate 을 원본 Terrain.mat 으로 되돌리면 끝. public static class WL814q_Polish { const string ScenePath = "Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity"; const string SrcMat = "Assets/3DPixelArtEnvironment/Materials/Terrain.mat"; const string MatDir = "Assets/WL/Look/Arena/Materials"; const string NewMat = MatDir + "/WL_ArenaTerrain.mat"; public static string Run() { var sb = new System.Text.StringBuilder(); if (!UnityEditor.AssetDatabase.IsValidFolder(MatDir)) UnityEditor.AssetDatabase.CreateFolder("Assets/WL/Look/Arena", "Materials"); if (UnityEditor.AssetDatabase.LoadAssetAtPath(NewMat) == null) { if (!UnityEditor.AssetDatabase.CopyAsset(SrcMat, NewMat)) return "CopyAsset FAILED"; UnityEditor.AssetDatabase.Refresh(); } var m = UnityEditor.AssetDatabase.LoadAssetAtPath(NewMat); if (m == null) return "NEW MAT NOT FOUND"; // 데모 원본: _GreenHighlight(0.840,0.830,0.646 카키) → 렌더 결과가 풀과 거의 같은 초록(실측 152,188,119 vs 170,203,126) // 전투장 바닥이 흙으로 읽히도록 이 채널만 Trunk.mat 계열 따뜻한 흙색으로 바꾼다. 나머지 값은 원본 그대로. m.SetColor("_GreenHighlight", new UnityEngine.Color(0.7924528f, 0.6389284f, 0.5121039f, 0f)); m.SetColor("_GreenShadow", new UnityEngine.Color(0.3254902f, 0.2352941f, 0.1490196f, 0f)); UnityEditor.EditorUtility.SetDirty(m); UnityEditor.AssetDatabase.SaveAssets(); sb.AppendLine("MAT " + NewMat + " _GreenHighlight=" + m.GetColor("_GreenHighlight")); var scene = UnityEditor.SceneManagement.EditorSceneManager.OpenScene(ScenePath, UnityEditor.SceneManagement.OpenSceneMode.Single); var t = UnityEngine.Object.FindFirstObjectByType(); if (t == null) return sb + "NO TERRAIN"; t.materialTemplate = m; UnityEditor.EditorUtility.SetDirty(t); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene, ScenePath); UnityEditor.AssetDatabase.SaveAssets(); sb.AppendLine("Terrain.materialTemplate = " + t.materialTemplate.name + " (shader " + t.materialTemplate.shader.name + ")"); return sb.ToString(); } /// 실측 결과 되돌리기 — ToonTerrain 은 터레인 스플랫을 쓰지 않는다(Probe3 실측: /// _RedHighlight 만 화면에 나오고 _GreenHighlight 는 어디에도 안 나온다). 흙 채널 변형은 의미가 없으므로 /// 데모 원본 Terrain.mat 로 되돌리고 만들었던 변형 머티리얼은 지운다 = 데모와 편차 0. public static string Revert() { var scene = UnityEditor.SceneManagement.EditorSceneManager.OpenScene(ScenePath, UnityEditor.SceneManagement.OpenSceneMode.Single); var t = UnityEngine.Object.FindFirstObjectByType(); if (t == null) return "NO TERRAIN"; t.materialTemplate = UnityEditor.AssetDatabase.LoadAssetAtPath(SrcMat); UnityEditor.EditorUtility.SetDirty(t); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene); UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene, ScenePath); UnityEditor.AssetDatabase.DeleteAsset(NewMat); UnityEditor.AssetDatabase.DeleteAsset(MatDir); UnityEditor.AssetDatabase.SaveAssets(); UnityEditor.AssetDatabase.Refresh(); return "Terrain.materialTemplate = " + t.materialTemplate.name + " (원본) · 변형 머티리얼 삭제"; } /// 캐릭터 실측 — 무기 제외 몸 높이 · 전체 바운즈 · 바인드포즈 기준 높이. public static string MeasurePc() { UnityEditor.SceneManagement.EditorSceneManager.OpenScene(ScenePath, UnityEditor.SceneManagement.OpenSceneMode.Single); var pc = UnityEngine.GameObject.Find("PC_LH_M05"); if (pc == null) return "PC NOT FOUND"; var all = new UnityEngine.Bounds(); var body = new UnityEngine.Bounds(); bool fa = true, fb = true; foreach (var r in pc.GetComponentsInChildren(true)) { if (fa) { all = r.bounds; fa = false; } else all.Encapsulate(r.bounds); bool weapon = false; foreach (var mm in r.sharedMaterials) if (mm != null && mm.name.ToLower().Contains("sword")) weapon = true; if (weapon) continue; if (fb) { body = r.bounds; fb = false; } else body.Encapsulate(r.bounds); } // 바인드 포즈(원 프리팹) 기준 높이 — 인게임 기준값과 대조용 var src = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Res_Addr/PC/LH_M05.prefab"); var tmp = (UnityEngine.GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(src); tmp.transform.position = UnityEngine.Vector3.zero; tmp.transform.localScale = UnityEngine.Vector3.one * (0.7f * 1.5038f); var bp = new UnityEngine.Bounds(); bool fc = true; foreach (var r in tmp.GetComponentsInChildren(true)) { if (fc) { bp = r.bounds; fc = false; } else bp.Encapsulate(r.bounds); } UnityEngine.Object.DestroyImmediate(tmp); return string.Format( "PC scale={0:F5} · 바인드포즈 바운즈 높이={1:F4} m · 씬(Idle 포즈) 몸(무기 제외)={2:F4} m · 전체(무기 포함)={3:F4} m · 발끝 y={4:F4}", 0.7f * 1.5038f, bp.size.y, body.size.y, all.size.y, body.min.y); } }