using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; using System; /// /// 地形切分 引擎工具类 /// public class MySplitTerrain : EditorWindow { // 目标地形 private Terrain LargeTargetTerrain; // 目标数据 private TerrainData LargeTargetData; // 切分次数 private int TerrainNum = 4; // private int TerrainNumKH = 2; // 地图切片 private Terrain[,] IndividualTerrain; // 地图切片数据 private TerrainData[,] IndividualTerrainData; // 宽长高 private float W, L, H; private float X, Z; // 缩放 private Vector3 scale; // 植被数量 private TreeInstance[] TreeNum; private GameObject[] treeainS; private int Pixel_Error = 200; private int Base_Map_Dist = 30; private bool Cast_Shadows = true; private Material Material; private bool Draw = true; private int Detail_Distance = 30; private float Detail_Density = 1f; private int Tree_Distance = 30; private int Billboad_Start = 30; private int Fabe_Length = 5; private int Max_Mesh_Trees = 30; private float Speed = 0.5f; private float Size = 0.5f; private float Bending = 0.5f; private Color Grass_Tint = new Color(0.7F, 0.6F, 0.5F, 0); private Vector2 scrollPosTerrain; [MenuItem("地图/地形切分工具")] public static void OpenSplitTerrainWindow() { EditorWindow.GetWindow(typeof(MySplitTerrain)); } void Update() { } void OnGUI() { GUILayout.Label("目标地形预制体"); LargeTargetTerrain = EditorGUILayout.ObjectField(LargeTargetTerrain, typeof(Terrain), true) as Terrain; GUILayout.Label("切分数量2的幂"); //248 TerrainNumKH = EditorGUILayout.IntField(TerrainNumKH); if (!Mathf.IsPowerOfTwo(TerrainNumKH)) { return; } if (GUILayout.Button("生成")) { Split(); } GUILayout.BeginArea(new Rect(10, 120, 500, 700)); GUILayout.Label("地形数据检测"); GUILayout.Label("---Base Terrain---"); GUILayout.Label("像素误差"); Pixel_Error = (int)EditorGUILayout.Slider(Pixel_Error, 1, 200); GUILayout.Label("基础切片区域"); Base_Map_Dist = (int)EditorGUILayout.Slider(Base_Map_Dist, 0, 2000); //GUILayout.Label("Cast shadows"); Cast_Shadows = EditorGUILayout.Toggle("阴影品质", Cast_Shadows); //GUILayout.Label("Material"); //Material = EditorGUILayout.ObjectField(Material, typeof(Material), true) as Material; //GUILayout.Label("---Tree &Detail Objects---"); //// GUILayout.Label("Draw"); //Draw = EditorGUILayout.Toggle("Draw", Draw); //GUILayout.Label("细节距离"); //Detail_Distance = (int)EditorGUILayout.Slider(Detail_Distance, 0, 250); //GUILayout.Label("细节密度"); //Detail_Density = EditorGUILayout.Slider(Detail_Density, 0, 1); //GUILayout.Label("植被距离"); //Tree_Distance = (int)EditorGUILayout.Slider(Tree_Distance, 0, 2000); //GUILayout.Label("Billboad Start"); //Billboad_Start = (int)EditorGUILayout.Slider(Billboad_Start, 5, 2000); //GUILayout.Label("Fabe Length"); //Fabe_Length = (int)EditorGUILayout.Slider(Fabe_Length, 0, 200); //GUILayout.Label("Max Mesh Trees"); //Max_Mesh_Trees = (int)EditorGUILayout.Slider(Max_Mesh_Trees, 0, 10000); //GUILayout.Label("---Wind Settings---"); //GUILayout.Label("Speed"); //Speed = EditorGUILayout.Slider(Speed, 0, 1); //GUILayout.Label("Size"); //Size = EditorGUILayout.Slider(Size, 0, 1); //GUILayout.Label("Bending"); //Bending = EditorGUILayout.Slider(Bending, 0, 1); // GUILayout.Label("Grass Tint"); //Grass_Tint = EditorGUILayout.ColorField("Grass Tint", Grass_Tint); if (GUILayout.Button("地形批量修改")) { Terrainbatchchange(); } GUILayout.EndArea(); GUILayout.BeginArea(new Rect(520, 120, 300, 700)); GUILayout.Label("Treeain) "); if (GUILayout.Button("地形列表")) { GetTerrainNumList(); } scrollPosTerrain = GUILayout.BeginScrollView(scrollPosTerrain, GUILayout.Width(300), GUILayout.Height(500)); if (treeainS != null) for (int i = 0; i < treeainS.Length; i++) { treeainS[i] = EditorGUILayout.ObjectField(treeainS[i], typeof(GameObject), true) as GameObject; } GUILayout.EndScrollView(); GUILayout.EndArea(); GUILayout.Space(20); } void GetTerrainNumList() { treeainS = GameObject.FindGameObjectsWithTag("Terrain"); } void Terrainbatchchange() { for (int i = 0; i < treeainS.Length; i++) { treeainS[i].GetComponent().heightmapPixelError = LargeTargetTerrain.heightmapPixelError; treeainS[i].GetComponent().basemapDistance = LargeTargetTerrain.basemapDistance; treeainS[i].GetComponent().castShadows = LargeTargetTerrain.castShadows; treeainS[i].GetComponent().materialTemplate = LargeTargetTerrain.materialTemplate; treeainS[i].GetComponent().enabled = LargeTargetTerrain.enabled; treeainS[i].GetComponent().detailObjectDistance = LargeTargetTerrain.detailObjectDistance; treeainS[i].GetComponent().detailObjectDensity = LargeTargetTerrain.detailObjectDensity; treeainS[i].GetComponent().treeDistance = LargeTargetTerrain.treeDistance; treeainS[i].GetComponent().treeBillboardDistance = LargeTargetTerrain.treeBillboardDistance; treeainS[i].GetComponent().treeCrossFadeLength = LargeTargetTerrain.treeCrossFadeLength; treeainS[i].GetComponent().treeMaximumFullLODCount = LargeTargetTerrain.treeMaximumFullLODCount; treeainS[i].GetComponent().terrainData.wavingGrassStrength = LargeTargetTerrain.terrainData.wavingGrassStrength; treeainS[i].GetComponent().terrainData.wavingGrassSpeed = LargeTargetTerrain.terrainData.wavingGrassSpeed; treeainS[i].GetComponent().terrainData.wavingGrassAmount = LargeTargetTerrain.terrainData.wavingGrassAmount; treeainS[i].GetComponent().terrainData.wavingGrassTint = LargeTargetTerrain.terrainData.wavingGrassTint; treeainS[i].GetComponent().terrainData.terrainLayers = LargeTargetData.terrainLayers; } } void Split() { GetDataLargeTargetTerrain(); IndividualTerrainCreat(); divisionTreeainData(); DiveisionTreeatinAlphamapData(); DiveisionTreeatinTree(); DiveisionTreeatinGrass(); } void GetDataLargeTargetTerrain() { LargeTargetData = LargeTargetTerrain.terrainData; scale = LargeTargetData.size; TreeNum = LargeTargetData.treeInstances; } void IndividualTerrainCreat() { TerrainNum = TerrainNumKH * TerrainNumKH; try { double num = Mathf.Sqrt(TerrainNum); string str = num.ToString(); str = str.Substring(str.LastIndexOf('.'), 2); } catch (Exception) { string path = AssetDatabase.GetAssetPath(LargeTargetTerrain); if(path == "") { return; } W = LargeTargetTerrain.terrainData.size.x; H = LargeTargetTerrain.terrainData.size.y; L = LargeTargetTerrain.terrainData.size.z; TerrainNumKH = (int)Mathf.Sqrt(TerrainNum); IndividualTerrainData = new TerrainData[TerrainNumKH, TerrainNumKH]; IndividualTerrain = new Terrain[TerrainNumKH, TerrainNumKH]; Vector3[,] TerrainPoint = new Vector3[TerrainNumKH, TerrainNumKH]; X = W / TerrainNumKH; Z = W / TerrainNumKH; for (int i = 0; i < TerrainNumKH; i++) { for (int j = 0; j < TerrainNumKH; j++) { IndividualTerrainData[i, j] = new TerrainData(); IndividualTerrain[i, j] = Terrain.CreateTerrainGameObject(IndividualTerrainData[i, j]).GetComponent(); TerrainPoint[i, j] = new Vector3(i * X, 0, j * Z); IndividualTerrainData[i, j].heightmapResolution = (int)LargeTargetData.heightmapResolution / TerrainNumKH; IndividualTerrainData[i, j].size = new Vector3(W / TerrainNumKH, LargeTargetData.size.y, L / TerrainNumKH); IndividualTerrain[i, j].transform.position = TerrainPoint[i, j]; IndividualTerrain[i, j].transform.name = (IndividualTerrain[i, j].transform.name + i + j); IndividualTerrain[i, j].heightmapPixelError = LargeTargetTerrain.heightmapPixelError; IndividualTerrain[i, j].basemapDistance = LargeTargetTerrain.basemapDistance; IndividualTerrain[i, j].castShadows = LargeTargetTerrain.castShadows; IndividualTerrain[i, j].reflectionProbeUsage = LargeTargetTerrain.reflectionProbeUsage; IndividualTerrain[i, j].materialTemplate = LargeTargetTerrain.materialTemplate; IndividualTerrain[i, j].enabled = LargeTargetTerrain.enabled; IndividualTerrain[i, j].detailObjectDistance = LargeTargetTerrain.detailObjectDistance; IndividualTerrain[i, j].detailObjectDensity = LargeTargetTerrain.detailObjectDensity; IndividualTerrain[i, j].treeDistance = LargeTargetTerrain.treeDistance; IndividualTerrain[i, j].treeBillboardDistance = LargeTargetTerrain.treeBillboardDistance; IndividualTerrain[i, j].treeCrossFadeLength = LargeTargetTerrain.treeCrossFadeLength; IndividualTerrain[i, j].treeMaximumFullLODCount = LargeTargetTerrain.treeMaximumFullLODCount; IndividualTerrain[i, j].terrainData.wavingGrassStrength = LargeTargetTerrain.terrainData.wavingGrassStrength; IndividualTerrain[i, j].terrainData.wavingGrassSpeed = LargeTargetTerrain.terrainData.wavingGrassSpeed; IndividualTerrain[i, j].terrainData.wavingGrassAmount = LargeTargetTerrain.terrainData.wavingGrassAmount; IndividualTerrain[i, j].terrainData.wavingGrassTint = LargeTargetTerrain.terrainData.wavingGrassTint; IndividualTerrain[i, j].terrainData.terrainLayers = LargeTargetData.terrainLayers; IndividualTerrain[i, j].transform.parent = LargeTargetTerrain.transform; MySplitTerrainTile mystt = IndividualTerrain[i, j].gameObject.GetOrAddComponent(); mystt.refreshTime = 1; AssetDatabase.CreateAsset(IndividualTerrainData[i, j], AssetDatabase.GetAssetPath(LargeTargetTerrain) + IndividualTerrain[i, j].transform.name + i + j + ".asset"); } } } } void divisionTreeainData() { for (int i = 0; i < TerrainNumKH; i++) { for (int j = 0; j < TerrainNumKH; j++) { IndividualTerrain[i, j].basemapDistance = 100; int X, Y; X = LargeTargetData.heightmapResolution / TerrainNumKH; Y = LargeTargetData.heightmapResolution / TerrainNumKH; float[,] height = LargeTargetData.GetHeights(X * i, Y * j, X + 1, Y + 1); IndividualTerrainData[i, j].SetHeights(0, 0, height); } } } void DiveisionTreeatinAlphamapData() { for (int i = 0; i < TerrainNumKH; i++) { for (int j = 0; j < TerrainNumKH; j++) { int X, Y; X = LargeTargetData.alphamapWidth / TerrainNumKH; Y = LargeTargetData.alphamapHeight / TerrainNumKH; float[,,] aMap = LargeTargetData.GetAlphamaps(X * i, Y * j, X, Y); IndividualTerrainData[i, j].alphamapResolution = LargeTargetData.alphamapResolution / TerrainNumKH; //IndividualTerrainData[i, j].splatPrototypes = LargeTargetData.splatPrototypes; IndividualTerrainData[i, j].SetAlphamaps(0, 0, aMap); } } } void DiveisionTreeatinTree() { List TreesPoint = new List(); for (int k = 0; k < TreeNum.Length; k++) { Vector3 treespoint = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L); TreesPoint.Add(treespoint); } for (int i = 0; i < TerrainNumKH; i++) { for (int j = 0; j < TerrainNumKH; j++) { IndividualTerrainData[i, j].treePrototypes = LargeTargetData.treePrototypes; Vector3 IndividualTerrainSize = IndividualTerrain[i, j].terrainData.size; Vector3 IndividualTerrainPoint = IndividualTerrain[i, j].transform.position; Rect rect = new Rect(IndividualTerrainPoint.x, IndividualTerrainPoint.z, IndividualTerrainSize.x, IndividualTerrainSize.z); List trees = new List(); trees.Clear(); for (int k = 0; k < TreeNum.Length; k++) { if (rect.Contains(new Vector2(TreeNum[k].position.x * W, TreeNum[k].position.z * L))) { Vector3 treesList = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L); for (int p = 0; p < TreesPoint.Count; p++) { if (treesList == TreesPoint[p]) { Vector3 ScreenTreeS = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L); Vector3 ZDTreeS = new Vector3(ScreenTreeS.x - IndividualTerrainPoint.x, ScreenTreeS.y, ScreenTreeS.z - IndividualTerrainPoint.z); Vector3 shareTree = new Vector3(ZDTreeS.x / IndividualTerrainSize.x, ZDTreeS.y / IndividualTerrainSize.y, ZDTreeS.z / IndividualTerrainSize.z); TreeNum[k].position = shareTree; trees.Add(TreeNum[k]); } } } } IndividualTerrainData[i, j].treeInstances = trees.ToArray(); } } } void DiveisionTreeatinGrass() { DetailPrototype[] Grass = LargeTargetData.detailPrototypes; int LargetSize = LargeTargetData.detailResolution; for (int i = 0; i < TerrainNumKH; i++) { for (int j = 0; j < TerrainNumKH; j++) { IndividualTerrainData[i, j].detailPrototypes = Grass; IndividualTerrainData[i, j].SetDetailResolution(LargetSize / TerrainNumKH, 8); for (int k = 0; k < Grass.Length; k++) { int[,] text = LargeTargetData.GetDetailLayer(LargetSize / TerrainNumKH * i, LargetSize / TerrainNumKH * j, LargetSize / TerrainNumKH, LargetSize / TerrainNumKH, k); IndividualTerrainData[i, j].SetDetailLayer(0, 0, k, text); } } } } }