MySplitTerrain.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System;
  6. /// <summary>
  7. /// 地形切分 引擎工具类
  8. /// </summary>
  9. public class MySplitTerrain : EditorWindow
  10. {
  11. // 目标地形
  12. private Terrain LargeTargetTerrain;
  13. // 目标数据
  14. private TerrainData LargeTargetData;
  15. // 切分次数
  16. private int TerrainNum = 4;
  17. //
  18. private int TerrainNumKH = 2;
  19. // 地图切片
  20. private Terrain[,] IndividualTerrain;
  21. // 地图切片数据
  22. private TerrainData[,] IndividualTerrainData;
  23. // 宽长高
  24. private float W, L, H;
  25. private float X, Z;
  26. // 缩放
  27. private Vector3 scale;
  28. // 植被数量
  29. private TreeInstance[] TreeNum;
  30. private GameObject[] treeainS;
  31. private int Pixel_Error = 200;
  32. private int Base_Map_Dist = 30;
  33. private bool Cast_Shadows = true;
  34. private Material Material;
  35. private bool Draw = true;
  36. private int Detail_Distance = 30;
  37. private float Detail_Density = 1f;
  38. private int Tree_Distance = 30;
  39. private int Billboad_Start = 30;
  40. private int Fabe_Length = 5;
  41. private int Max_Mesh_Trees = 30;
  42. private float Speed = 0.5f;
  43. private float Size = 0.5f;
  44. private float Bending = 0.5f;
  45. private Color Grass_Tint = new Color(0.7F, 0.6F, 0.5F, 0);
  46. private Vector2 scrollPosTerrain;
  47. [MenuItem("地图/地形切分工具")]
  48. public static void OpenSplitTerrainWindow()
  49. {
  50. EditorWindow.GetWindow(typeof(MySplitTerrain));
  51. }
  52. void Update()
  53. {
  54. }
  55. void OnGUI()
  56. {
  57. GUILayout.Label("目标地形预制体");
  58. LargeTargetTerrain = EditorGUILayout.ObjectField(LargeTargetTerrain, typeof(Terrain), true) as Terrain;
  59. GUILayout.Label("切分数量2的幂");
  60. //248
  61. TerrainNumKH = EditorGUILayout.IntField(TerrainNumKH);
  62. if (!Mathf.IsPowerOfTwo(TerrainNumKH))
  63. {
  64. return;
  65. }
  66. if (GUILayout.Button("生成"))
  67. {
  68. Split();
  69. }
  70. GUILayout.BeginArea(new Rect(10, 120, 500, 700));
  71. GUILayout.Label("地形数据检测");
  72. GUILayout.Label("---Base Terrain---");
  73. GUILayout.Label("像素误差");
  74. Pixel_Error = (int)EditorGUILayout.Slider(Pixel_Error, 1, 200);
  75. GUILayout.Label("基础切片区域");
  76. Base_Map_Dist = (int)EditorGUILayout.Slider(Base_Map_Dist, 0, 2000);
  77. //GUILayout.Label("Cast shadows");
  78. Cast_Shadows = EditorGUILayout.Toggle("阴影品质", Cast_Shadows);
  79. //GUILayout.Label("Material");
  80. //Material = EditorGUILayout.ObjectField(Material, typeof(Material), true) as Material;
  81. //GUILayout.Label("---Tree &Detail Objects---");
  82. //// GUILayout.Label("Draw");
  83. //Draw = EditorGUILayout.Toggle("Draw", Draw);
  84. //GUILayout.Label("细节距离");
  85. //Detail_Distance = (int)EditorGUILayout.Slider(Detail_Distance, 0, 250);
  86. //GUILayout.Label("细节密度");
  87. //Detail_Density = EditorGUILayout.Slider(Detail_Density, 0, 1);
  88. //GUILayout.Label("植被距离");
  89. //Tree_Distance = (int)EditorGUILayout.Slider(Tree_Distance, 0, 2000);
  90. //GUILayout.Label("Billboad Start");
  91. //Billboad_Start = (int)EditorGUILayout.Slider(Billboad_Start, 5, 2000);
  92. //GUILayout.Label("Fabe Length");
  93. //Fabe_Length = (int)EditorGUILayout.Slider(Fabe_Length, 0, 200);
  94. //GUILayout.Label("Max Mesh Trees");
  95. //Max_Mesh_Trees = (int)EditorGUILayout.Slider(Max_Mesh_Trees, 0, 10000);
  96. //GUILayout.Label("---Wind Settings---");
  97. //GUILayout.Label("Speed");
  98. //Speed = EditorGUILayout.Slider(Speed, 0, 1);
  99. //GUILayout.Label("Size");
  100. //Size = EditorGUILayout.Slider(Size, 0, 1);
  101. //GUILayout.Label("Bending");
  102. //Bending = EditorGUILayout.Slider(Bending, 0, 1);
  103. // GUILayout.Label("Grass Tint");
  104. //Grass_Tint = EditorGUILayout.ColorField("Grass Tint", Grass_Tint);
  105. if (GUILayout.Button("地形批量修改"))
  106. {
  107. Terrainbatchchange();
  108. }
  109. GUILayout.EndArea();
  110. GUILayout.BeginArea(new Rect(520, 120, 300, 700));
  111. GUILayout.Label("Treeain) ");
  112. if (GUILayout.Button("地形列表"))
  113. {
  114. GetTerrainNumList();
  115. }
  116. scrollPosTerrain = GUILayout.BeginScrollView(scrollPosTerrain, GUILayout.Width(300), GUILayout.Height(500));
  117. if (treeainS != null)
  118. for (int i = 0; i < treeainS.Length; i++)
  119. {
  120. treeainS[i] = EditorGUILayout.ObjectField(treeainS[i], typeof(GameObject), true) as GameObject;
  121. }
  122. GUILayout.EndScrollView();
  123. GUILayout.EndArea();
  124. GUILayout.Space(20);
  125. }
  126. void GetTerrainNumList()
  127. {
  128. treeainS = GameObject.FindGameObjectsWithTag("Terrain");
  129. }
  130. void Terrainbatchchange()
  131. {
  132. for (int i = 0; i < treeainS.Length; i++)
  133. {
  134. treeainS[i].GetComponent<Terrain>().heightmapPixelError = LargeTargetTerrain.heightmapPixelError;
  135. treeainS[i].GetComponent<Terrain>().basemapDistance = LargeTargetTerrain.basemapDistance;
  136. treeainS[i].GetComponent<Terrain>().castShadows = LargeTargetTerrain.castShadows;
  137. treeainS[i].GetComponent<Terrain>().materialTemplate = LargeTargetTerrain.materialTemplate;
  138. treeainS[i].GetComponent<Terrain>().enabled = LargeTargetTerrain.enabled;
  139. treeainS[i].GetComponent<Terrain>().detailObjectDistance = LargeTargetTerrain.detailObjectDistance;
  140. treeainS[i].GetComponent<Terrain>().detailObjectDensity = LargeTargetTerrain.detailObjectDensity;
  141. treeainS[i].GetComponent<Terrain>().treeDistance = LargeTargetTerrain.treeDistance;
  142. treeainS[i].GetComponent<Terrain>().treeBillboardDistance = LargeTargetTerrain.treeBillboardDistance;
  143. treeainS[i].GetComponent<Terrain>().treeCrossFadeLength = LargeTargetTerrain.treeCrossFadeLength;
  144. treeainS[i].GetComponent<Terrain>().treeMaximumFullLODCount = LargeTargetTerrain.treeMaximumFullLODCount;
  145. treeainS[i].GetComponent<Terrain>().terrainData.wavingGrassStrength = LargeTargetTerrain.terrainData.wavingGrassStrength;
  146. treeainS[i].GetComponent<Terrain>().terrainData.wavingGrassSpeed = LargeTargetTerrain.terrainData.wavingGrassSpeed;
  147. treeainS[i].GetComponent<Terrain>().terrainData.wavingGrassAmount = LargeTargetTerrain.terrainData.wavingGrassAmount;
  148. treeainS[i].GetComponent<Terrain>().terrainData.wavingGrassTint = LargeTargetTerrain.terrainData.wavingGrassTint;
  149. treeainS[i].GetComponent<Terrain>().terrainData.terrainLayers = LargeTargetData.terrainLayers;
  150. }
  151. }
  152. void Split()
  153. {
  154. GetDataLargeTargetTerrain();
  155. IndividualTerrainCreat();
  156. divisionTreeainData();
  157. DiveisionTreeatinAlphamapData();
  158. DiveisionTreeatinTree();
  159. DiveisionTreeatinGrass();
  160. }
  161. void GetDataLargeTargetTerrain()
  162. {
  163. LargeTargetData = LargeTargetTerrain.terrainData;
  164. scale = LargeTargetData.size;
  165. TreeNum = LargeTargetData.treeInstances;
  166. }
  167. void IndividualTerrainCreat()
  168. {
  169. TerrainNum = TerrainNumKH * TerrainNumKH;
  170. try
  171. {
  172. double num = Mathf.Sqrt(TerrainNum);
  173. string str = num.ToString();
  174. str = str.Substring(str.LastIndexOf('.'), 2);
  175. }
  176. catch (Exception)
  177. {
  178. string path = AssetDatabase.GetAssetPath(LargeTargetTerrain);
  179. if(path == "")
  180. {
  181. return;
  182. }
  183. W = LargeTargetTerrain.terrainData.size.x;
  184. H = LargeTargetTerrain.terrainData.size.y;
  185. L = LargeTargetTerrain.terrainData.size.z;
  186. TerrainNumKH = (int)Mathf.Sqrt(TerrainNum);
  187. IndividualTerrainData = new TerrainData[TerrainNumKH, TerrainNumKH];
  188. IndividualTerrain = new Terrain[TerrainNumKH, TerrainNumKH];
  189. Vector3[,] TerrainPoint = new Vector3[TerrainNumKH, TerrainNumKH];
  190. X = W / TerrainNumKH;
  191. Z = W / TerrainNumKH;
  192. for (int i = 0; i < TerrainNumKH; i++)
  193. {
  194. for (int j = 0; j < TerrainNumKH; j++)
  195. {
  196. IndividualTerrainData[i, j] = new TerrainData();
  197. IndividualTerrain[i, j] = Terrain.CreateTerrainGameObject(IndividualTerrainData[i, j]).GetComponent<Terrain>();
  198. TerrainPoint[i, j] = new Vector3(i * X, 0, j * Z);
  199. IndividualTerrainData[i, j].heightmapResolution = (int)LargeTargetData.heightmapResolution / TerrainNumKH;
  200. IndividualTerrainData[i, j].size = new Vector3(W / TerrainNumKH, LargeTargetData.size.y, L / TerrainNumKH);
  201. IndividualTerrain[i, j].transform.position = TerrainPoint[i, j];
  202. IndividualTerrain[i, j].transform.name = (IndividualTerrain[i, j].transform.name + i + j);
  203. IndividualTerrain[i, j].heightmapPixelError = LargeTargetTerrain.heightmapPixelError;
  204. IndividualTerrain[i, j].basemapDistance = LargeTargetTerrain.basemapDistance;
  205. IndividualTerrain[i, j].castShadows = LargeTargetTerrain.castShadows;
  206. IndividualTerrain[i, j].reflectionProbeUsage = LargeTargetTerrain.reflectionProbeUsage;
  207. IndividualTerrain[i, j].materialTemplate = LargeTargetTerrain.materialTemplate;
  208. IndividualTerrain[i, j].enabled = LargeTargetTerrain.enabled;
  209. IndividualTerrain[i, j].detailObjectDistance = LargeTargetTerrain.detailObjectDistance;
  210. IndividualTerrain[i, j].detailObjectDensity = LargeTargetTerrain.detailObjectDensity;
  211. IndividualTerrain[i, j].treeDistance = LargeTargetTerrain.treeDistance;
  212. IndividualTerrain[i, j].treeBillboardDistance = LargeTargetTerrain.treeBillboardDistance;
  213. IndividualTerrain[i, j].treeCrossFadeLength = LargeTargetTerrain.treeCrossFadeLength;
  214. IndividualTerrain[i, j].treeMaximumFullLODCount = LargeTargetTerrain.treeMaximumFullLODCount;
  215. IndividualTerrain[i, j].terrainData.wavingGrassStrength = LargeTargetTerrain.terrainData.wavingGrassStrength;
  216. IndividualTerrain[i, j].terrainData.wavingGrassSpeed = LargeTargetTerrain.terrainData.wavingGrassSpeed;
  217. IndividualTerrain[i, j].terrainData.wavingGrassAmount = LargeTargetTerrain.terrainData.wavingGrassAmount;
  218. IndividualTerrain[i, j].terrainData.wavingGrassTint = LargeTargetTerrain.terrainData.wavingGrassTint;
  219. IndividualTerrain[i, j].terrainData.terrainLayers = LargeTargetData.terrainLayers;
  220. IndividualTerrain[i, j].transform.parent = LargeTargetTerrain.transform;
  221. MySplitTerrainTile mystt = IndividualTerrain[i, j].gameObject.GetOrAddComponent<MySplitTerrainTile>();
  222. mystt.refreshTime = 1;
  223. AssetDatabase.CreateAsset(IndividualTerrainData[i, j], AssetDatabase.GetAssetPath(LargeTargetTerrain) + IndividualTerrain[i, j].transform.name + i + j + ".asset");
  224. }
  225. }
  226. }
  227. }
  228. void divisionTreeainData()
  229. {
  230. for (int i = 0; i < TerrainNumKH; i++)
  231. {
  232. for (int j = 0; j < TerrainNumKH; j++)
  233. {
  234. IndividualTerrain[i, j].basemapDistance = 100;
  235. int X, Y;
  236. X = LargeTargetData.heightmapResolution / TerrainNumKH;
  237. Y = LargeTargetData.heightmapResolution / TerrainNumKH;
  238. float[,] height = LargeTargetData.GetHeights(X * i, Y * j, X + 1, Y + 1);
  239. IndividualTerrainData[i, j].SetHeights(0, 0, height);
  240. }
  241. }
  242. }
  243. void DiveisionTreeatinAlphamapData()
  244. {
  245. for (int i = 0; i < TerrainNumKH; i++)
  246. {
  247. for (int j = 0; j < TerrainNumKH; j++)
  248. {
  249. int X, Y;
  250. X = LargeTargetData.alphamapWidth / TerrainNumKH;
  251. Y = LargeTargetData.alphamapHeight / TerrainNumKH;
  252. float[,,] aMap = LargeTargetData.GetAlphamaps(X * i, Y * j, X, Y);
  253. IndividualTerrainData[i, j].alphamapResolution = LargeTargetData.alphamapResolution / TerrainNumKH;
  254. //IndividualTerrainData[i, j].splatPrototypes = LargeTargetData.splatPrototypes;
  255. IndividualTerrainData[i, j].SetAlphamaps(0, 0, aMap);
  256. }
  257. }
  258. }
  259. void DiveisionTreeatinTree()
  260. {
  261. List<Vector3> TreesPoint = new List<Vector3>();
  262. for (int k = 0; k < TreeNum.Length; k++)
  263. {
  264. Vector3 treespoint = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L);
  265. TreesPoint.Add(treespoint);
  266. }
  267. for (int i = 0; i < TerrainNumKH; i++)
  268. {
  269. for (int j = 0; j < TerrainNumKH; j++)
  270. {
  271. IndividualTerrainData[i, j].treePrototypes = LargeTargetData.treePrototypes;
  272. Vector3 IndividualTerrainSize = IndividualTerrain[i, j].terrainData.size;
  273. Vector3 IndividualTerrainPoint = IndividualTerrain[i, j].transform.position;
  274. Rect rect = new Rect(IndividualTerrainPoint.x, IndividualTerrainPoint.z, IndividualTerrainSize.x, IndividualTerrainSize.z);
  275. List<TreeInstance> trees = new List<TreeInstance>();
  276. trees.Clear();
  277. for (int k = 0; k < TreeNum.Length; k++)
  278. {
  279. if (rect.Contains(new Vector2(TreeNum[k].position.x * W, TreeNum[k].position.z * L)))
  280. {
  281. Vector3 treesList = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L);
  282. for (int p = 0; p < TreesPoint.Count; p++)
  283. {
  284. if (treesList == TreesPoint[p])
  285. {
  286. Vector3 ScreenTreeS = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L);
  287. Vector3 ZDTreeS = new Vector3(ScreenTreeS.x - IndividualTerrainPoint.x, ScreenTreeS.y, ScreenTreeS.z - IndividualTerrainPoint.z);
  288. Vector3 shareTree = new Vector3(ZDTreeS.x / IndividualTerrainSize.x, ZDTreeS.y / IndividualTerrainSize.y, ZDTreeS.z / IndividualTerrainSize.z);
  289. TreeNum[k].position = shareTree;
  290. trees.Add(TreeNum[k]);
  291. }
  292. }
  293. }
  294. }
  295. IndividualTerrainData[i, j].treeInstances = trees.ToArray();
  296. }
  297. }
  298. }
  299. void DiveisionTreeatinGrass()
  300. {
  301. DetailPrototype[] Grass = LargeTargetData.detailPrototypes;
  302. int LargetSize = LargeTargetData.detailResolution;
  303. for (int i = 0; i < TerrainNumKH; i++)
  304. {
  305. for (int j = 0; j < TerrainNumKH; j++)
  306. {
  307. IndividualTerrainData[i, j].detailPrototypes = Grass;
  308. IndividualTerrainData[i, j].SetDetailResolution(LargetSize / TerrainNumKH, 8);
  309. for (int k = 0; k < Grass.Length; k++)
  310. {
  311. int[,] text = LargeTargetData.GetDetailLayer(LargetSize / TerrainNumKH * i, LargetSize / TerrainNumKH * j, LargetSize / TerrainNumKH, LargetSize / TerrainNumKH, k);
  312. IndividualTerrainData[i, j].SetDetailLayer(0, 0, k, text);
  313. }
  314. }
  315. }
  316. }
  317. }