实现:保留的原 1000×1000 正中间的 500×500,并且这个中间区域的中心点和世界坐标保持不变。
一、先确认坐标关系
假设原始 Terrain 是:
- 大小:1000 × 1000
- 中心位置:
(0, 0, 0) - 世界范围:
- X:
-500 到 +500 - Z:
-500 到 +500
- X:
那么正中间 500×500 区域是:
- X:
-250 到 +250 - Z:
-250 到 +250 - 中心点仍然是:
(0, 0, 0)
如果你原来的 Terrain 坐标不是从 -500 开始,而是从 0 开始:
- 原始范围:X
0~1000,Z0~1000 - 中心点:
(500, 0, 500) - 中间 500×500 区域:
- X:
250 ~ 750 - Z:
250 ~ 750 - 中心点:
(500, 0, 500)保持不变
- X:
所以你要裁的是:
以原地形中心点为中心,向内收缩 250 米后的正方形区域。
这个脚本会新建一个独立的 500×500 Terrain,保留原中心点位置,并生成独立 TerrainData。
cs
using UnityEditor;
using UnityEngine;
public static class TerrainCenterCrop
{
[MenuItem("Terrain/Extract Center 500x500")]
public static void ExtractCenter500()
{
GameObject selected = Selection.activeGameObject;
if (selected == null)
{
Debug.LogWarning("请先选中一个 Terrain GameObject");
return;
}
Terrain sourceTerrain = selected.GetComponent<Terrain>();
if (sourceTerrain == null)
{
Debug.LogWarning("选中对象不是 Terrain");
return;
}
TerrainData sourceData = sourceTerrain.terrainData;
int sourceResolution = sourceData.heightmapResolution;
int destResolution = sourceResolution / 2;
// 创建新的独立 TerrainData
TerrainData newTerrainData = new TerrainData();
newTerrainData.heightmapResolution = destResolution;
newTerrainData.size = new Vector3(500f, sourceData.size.y, 500f);
// 高度贴图分辨率也要减半
int alphaWidth = Mathf.Max(1, sourceData.alphamapWidth / 2);
int alphaHeight = Mathf.Max(1, sourceData.alphamapHeight / 2);
// 提取中心 25% ~ 75% 的高度数据
int startX = Mathf.FloorToInt(sourceResolution * 0.25f);
int startZ = Mathf.FloorToInt(sourceResolution * 0.25f);
float[,] centerHeights = sourceData.GetHeights(startX, startZ, destResolution, destResolution);
newTerrainData.SetHeights(0, 0, centerHeights);
// 复制地形层
newTerrainData.splatPrototypes = sourceData.splatPrototypes;
// 提取中心区域的贴图
int alphaStartX = Mathf.FloorToInt(sourceData.alphamapWidth * 0.25f);
int alphaStartZ = Mathf.FloorToInt(sourceData.alphamapHeight * 0.25f);
float[,,] centerAlphas = sourceData.GetAlphamaps(alphaStartX, alphaStartZ, alphaWidth, alphaHeight);
newTerrainData.SetAlphamaps(0, 0, centerAlphas);
// 保存新 TerrainData
AssetDatabase.CreateAsset(newTerrainData, "Assets/TerrainData_Center500x500.asset");
AssetDatabase.SaveAssets();
// 创建新 Terrain GameObject
GameObject newTerrainObject = Terrain.CreateTerrainGameObject(newTerrainData);
newTerrainObject.name = "Terrain_Center500x500";
// 关键:保持原中心点不变
newTerrainObject.transform.position = sourceTerrain.transform.position + new Vector3(250f, 0f, 250f);
// 自动选中新地形
Selection.activeGameObject = newTerrainObject;
Debug.Log("已提取原地形中心 500x500,中心点位置保持不变");
}
}
脚本使用方法
- 在 Unity 中创建脚本文件夹
Editor - 新建脚本
TerrainCenterCrop.cs - 把上面代码粘贴进去
- 选中原始 1000×1000 Terrain
- 点击菜单:
Terrain > Extract Center 500x500
执行后会生成一个新的:
Terrain_Center500x500TerrainData_Center500x500.asset
这个新地形是独立的,修改不会影响原地形。
为什么这个脚本中心点不会变?
因为它不是简单裁掉四周,而是按原地形坐标重新定位:
newTerrainObject.transform.position = sourceTerrain.transform.position + new Vector3(250f, 0f, 250f);
假设原始 Terrain 是 1000×1000,从 0 开始:
- 原始中心:
(500, 0, 500) - 新 500×500 地形中心也会保持在:
(500, 0, 500)