using System.Collections.Generic; using System.IO; using PhxhSDK; using UnityEngine; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine.Rendering; using Object = UnityEngine.Object; /// /// 地面处理工具类 /// public static class GroundUtils { /// /// 修改地面贴图及材质的路径 用于打包 /// public static void ChangeMapTextureAndMatPath(GameObject ground, string targetDir, string prefix, List groundRootNames, Transform rootTransform, Transform unpackedRoot) { if (ground == null) { Debug.LogError("找不到地面对象,无法修改地面贴图和材质路径"); return; } // 获取地面的渲染器 var renderer = ground.GetComponent(); if (renderer == null || renderer.sharedMaterial == null) { Debug.LogError("地面对象缺少渲染器或材质"); return; } // 确保目标目录存在 EnsureDirectoryExists(targetDir); // 处理材质和贴图 Dictionary matMapping = new Dictionary(); Dictionary texMapping = new Dictionary(); // 处理主地面材质 MaterialUtils.ProcessMaterialAndTexture(renderer.sharedMaterial, targetDir, prefix, matMapping, texMapping); // 处理groundRoot下的所有材质 foreach (var rootName in groundRootNames) { var rootObj = rootTransform.FindChildRecursive(rootName); if (rootObj != null) { var renderers = rootObj.GetComponentsInChildren(true); foreach (var r in renderers) { foreach (var mat in r.sharedMaterials) { if (mat != null) { MaterialUtils.ProcessMaterialAndTexture(mat, targetDir, prefix, matMapping, texMapping); } } } } } // 更新场景中地面对象的材质引用 MaterialUtils.UpdateGroundMaterialReferences(ground, matMapping); // 检查其他地面节点 foreach (var rootName in groundRootNames) { var rootObj = rootTransform.FindChildRecursive(rootName); if (rootObj != null) { var renderers = rootObj.GetComponentsInChildren(true); foreach (var r in renderers) { MaterialUtils.UpdateRendererMaterialReferences(r, matMapping); } } } // 解除预制体对原始贴图的引用 if (unpackedRoot != null) { // 如果Art节点是从预制体解包的,确保彻底断开所有引用 MaterialUtils.EnsureNoOriginalReferences(unpackedRoot.gameObject); } // 在整个场景中查找任何可能仍然引用原始材质或贴图的渲染器 MaterialUtils.FindAndReplaceAllMaterialReferences(matMapping); // 脏标记整个场景,确保所有改动都被保存 EditorSceneManager.MarkSceneDirty(ground.scene); // 保存所有更改 AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log("地面贴图和材质路径修改完成"); } /// /// 确保目录存在 /// private static void EnsureDirectoryExists(string dirPath) { if (!AssetDatabase.IsValidFolder(dirPath)) { string parentDir = Path.GetDirectoryName(dirPath); if (!AssetDatabase.IsValidFolder(parentDir)) { AssetDatabase.CreateFolder(Path.GetDirectoryName(parentDir), Path.GetFileName(parentDir)); } AssetDatabase.CreateFolder(parentDir, Path.GetFileName(dirPath)); AssetDatabase.Refresh(); } } /// /// 切割地面贴图 /// public static void SplitGroundTexture(GameObject ground, string groundSplitDir, string prefix, int splitWidth, int splitHeight) { if (ground == null) return; var renderer = ground.GetComponent(); if (renderer == null) return; var mat = renderer.sharedMaterial; if (mat == null) return; var texture = mat.mainTexture as Texture2D; if (texture == null) return; var groundParent = Object.Instantiate(ground, ground.transform.parent, true); groundParent.name = "Ground"; // 计算原始地面的大小 var originalScale = ground.transform.localScale; var originalWidth = originalScale.x; var originalHeight = originalScale.y; var originPos = -new Vector3(originalWidth / 2f, originalHeight / 2f, 0); groundParent.transform.localScale = Vector3.one; // 确保目录存在 EnsureDirectoryExists(groundSplitDir); var textures = SplitTextureUtil.SplitTexture(texture, splitWidth, splitHeight, groundSplitDir, prefix); // 计算每个分割块的大小(基于原始地面大小) var rowCount = textures.GetLength(0); var columnCount = textures.GetLength(1); var blockWidth = originalWidth / columnCount; var blockHeight = originalHeight / rowCount; for (int row = 0; row < rowCount; row++) { for (int column = 0; column < columnCount; column++) { var splitTexture = textures[row, column]; if (splitTexture == null) { Debug.LogError($"Failed to load split texture at row {row}, column {column}"); continue; } var splitGround = Object.Instantiate(ground, groundParent.transform, true); Object.DestroyImmediate(splitGround.GetComponent()); var splitName = $"{prefix}Ground_{row}_{column}"; splitGround.name = splitName; // 设置固定的quad大小,不随贴图尺寸变化 splitGround.transform.localScale = new Vector3(blockWidth, blockHeight, 1); // 创建并保存材质 var splitMat = Object.Instantiate(mat); splitMat.mainTexture = splitTexture; var matPath = $"{groundSplitDir}/{splitName}.mat"; AssetDatabase.CreateAsset(splitMat, matPath); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); // 重新加载保存后的材质 var savedMat = AssetDatabase.LoadAssetAtPath(matPath); if (savedMat == null) { Debug.LogError($"Failed to load saved material at {matPath}"); continue; } var meshRenderer = splitGround.GetComponent(); if (meshRenderer != null) { meshRenderer.sharedMaterial = savedMat; meshRenderer.shadowCastingMode = ShadowCastingMode.Off; } // 计算位置,使用固定的block大小 splitGround.transform.localPosition = originPos + new Vector3(column * blockWidth + blockWidth / 2f, row * blockHeight + blockHeight / 2f, 0); } } Object.DestroyImmediate(ground); Object.DestroyImmediate(groundParent.GetComponent()); Object.DestroyImmediate(groundParent.GetComponent()); var boxCollider = groundParent.gameObject.AddComponent(); boxCollider.size = new Vector3(200, 200, 1); boxCollider.center = new Vector3(0, 0, 0.5f); Object.DestroyImmediate(groundParent.GetComponent()); } }