Terrain地形剪裁

实现:保留的原 1000×1000 正中间的 500×500,并且这个中间区域的中心点和世界坐标保持不变。

一、先确认坐标关系

假设原始 Terrain 是:

  • 大小:1000 × 1000
  • 中心位置:(0, 0, 0)
  • 世界范围:
    • X:-500 到 +500
    • Z:-500 到 +500

那么正中间 500×500 区域是:

  • X:-250 到 +250
  • Z:-250 到 +250
  • 中心点仍然是:(0, 0, 0)

如果你原来的 Terrain 坐标不是从 -500 开始,而是从 0 开始:

  • 原始范围:X 0~1000,Z 0~1000
  • 中心点:(500, 0, 500)
  • 中间 500×500 区域:
    • X:250 ~ 750
    • Z:250 ~ 750
    • 中心点:(500, 0, 500) 保持不变

所以你要裁的是:

以原地形中心点为中心,向内收缩 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,中心点位置保持不变");
    }
}

脚本使用方法

  1. 在 Unity 中创建脚本文件夹 Editor
  2. 新建脚本 TerrainCenterCrop.cs
  3. 把上面代码粘贴进去
  4. 选中原始 1000×1000 Terrain
  5. 点击菜单:
    Terrain > Extract Center 500x500

执行后会生成一个新的:

  • Terrain_Center500x500
  • TerrainData_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)
相关推荐
小贺儿开发3 小时前
DeepSeek + Codex + MCP:Unity 游戏开发实测
科技·游戏·unity·ai·程序员·编程·deepseek
新的瑞拉公主3 小时前
Cocos plist 粒子一键导入 Unity:Editor 工具实现与参数映射
unity·游戏开发·cocos2d-x·粒子系统·editor工具
淡海水4 小时前
03-02-架构篇-Boehm GC架构解析
unity·架构·c#·gc·boehm
xcLeigh1 天前
Unity基础:Instantiate实例化——在运行时动态创建游戏物体
游戏·unity·游戏引擎·教程·instantiate
流浪打工人2 天前
Unity3d TimeLine中audio track的使用
unity
淡海水2 天前
02-07-原理篇-GC暂停时间的本质
开发语言·unity·c#·gc·暂停时间
WarPigs2 天前
UI路径配置SO>字典json工作流
ui·unity
淡海水2 天前
02-06-原理篇-增量式GC与并发GC
算法·unity·c#·并发·gc·增量
阿松爱学习3 天前
【Unity开发】Aspose.PDF的使用
unity·pdf·c#