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());
}
}