using UnityEngine;
using UnityEditor;
using System.IO;
public class TerrainDataSaver : MonoBehaviour
{
[Header("源 Terrain")]
public Terrain sourceTerrain;
[Header("保存路径(相对于 Assets)")]
public string savePath = "SavedTerrains/MyTerrainData.asset";
[ContextMenu("保存 TerrainData(含混合纹理)")]
public void SaveTerrainData()
{
if (sourceTerrain == null)
{
Debug.LogError("❌ 请指定源地形!");
return;
}
TerrainData sourceData = sourceTerrain.terrainData;
TerrainData newData = new TerrainData();
// ✅ 设置分辨率和大小
newData.heightmapResolution = sourceData.heightmapResolution;
newData.size = sourceData.size;
newData.baseMapResolution = sourceData.baseMapResolution;
newData.alphamapResolution = sourceData.alphamapResolution;
newData.SetDetailResolution(sourceData.detailResolution, 16);
// ✅ 设置 TerrainLayers(必须先设置)
newData.terrainLayers = sourceData.terrainLayers;
// ✅ 设置混合纹理(alphamap / splatmap)
float[,,] alphaMaps = sourceData.GetAlphamaps(0, 0, sourceData.alphamapWidth, sourceData.alphamapHeight);
newData.SetAlphamaps(0, 0, alphaMaps);
// ✅ 设置树
newData.treePrototypes = sourceData.treePrototypes;
newData.treeInstances = sourceData.treeInstances;
// ✅ 设置草(细节)
newData.detailPrototypes = sourceData.detailPrototypes;
for (int i = 0; i < sourceData.detailPrototypes.Length; i++)
{
int[,] detailLayer = sourceData.GetDetailLayer(0, 0, sourceData.detailWidth, sourceData.detailHeight, i);
newData.SetDetailLayer(0, 0, i, detailLayer);
}
// ✅ 设置高度图(必须最后设置)
float[,] heights = sourceData.GetHeights(0, 0, sourceData.heightmapResolution, sourceData.heightmapResolution);
newData.SetHeights(0, 0, heights);
// ✅ 保存 .asset 文件
string fullPath = "Assets/" + savePath;
string folderPath = Path.GetDirectoryName(fullPath);
if (!AssetDatabase.IsValidFolder(folderPath))
{
Directory.CreateDirectory(folderPath);
AssetDatabase.Refresh();
}
AssetDatabase.CreateAsset(newData, fullPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"✅ TerrainData 保存成功(含纹理混合):{fullPath}");
}
[ContextMenu("导出第一层混合纹理为 PNG")]
public void ExportSplatmapLayer0ToPNG()
{
if (sourceTerrain == null)
{
Debug.LogError("❌ 请指定源地形!");
return;
}
TerrainData td = sourceTerrain.terrainData;
int width = td.alphamapWidth;
int height = td.alphamapHeight;
float[,,] alphamaps = td.GetAlphamaps(0, 0, width, height);
Texture2D tex = new Texture2D(width, height);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
float value = alphamaps[y, x, 0]; // 第一图层
tex.SetPixel(x, y, new Color(value, value, value, 1));
}
}
tex.Apply();
string exportPath = Application.dataPath + "/SplatLayer0.png";
File.WriteAllBytes(exportPath, tex.EncodeToPNG());
AssetDatabase.Refresh();
Debug.Log("✅ Splatmap Layer 0 导出成功:" + exportPath);
}
}
使用方式:
创建一个空 GameObject,挂上此脚本;
拖入你的地形 sourceTerrain;
设置保存路径(例如:SavedTerrains/Level01.asset);
在 Inspector 三点菜单点击 → 保存完整 TerrainData(含纹理混合)。
✅ 生成结果包括:
类型 文件扩展名 储存内容
.asset MyTerrainData.asset 包含高度图、混合图、草、树
.terrainlayer Layer_0.terrainlayer 等 储存每个纹理层贴图及参数