void Create() { // check lighting auto bake if (m_Settings.EnableLightingAutoBake) { UnityEditor.Lightmapping.giWorkflowMode = UnityEditor.Lightmapping.GIWorkflowMode.Iterative; } else { UnityEditor.Lightmapping.giWorkflowMode = UnityEditor.Lightmapping.GIWorkflowMode.OnDemand; } if (m_Settings.EnableClearExistingData) { ClearExistingTerrainGroup(m_Settings.GroupID); } // create tiles int tileCount = m_Settings.TilesX * m_Settings.TilesZ; Vector2Int tileOffset = Vector2Int.zero; Vector2Int tileOffsetSource = Vector2Int.zero; Vector2Int tileResolution = new Vector2Int(m_Settings.TerrainWidth / m_Settings.TilesX, m_Settings.TerrainLength / m_Settings.TilesZ); Vector3 tileSize = new Vector3(tileResolution.x, m_Settings.TerrainHeight, tileResolution.y); Vector3 tilePosition = m_Settings.StartPosition; Terrain[] terrains = new Terrain[tileCount]; string assetFolderPath = GetAssetPathFromFullPath(m_Settings.TerrainAssetDirectory); int tileIndex = 0; try { // create terrain grouping object string groupName = "TerrainGroup_" + m_Settings.GroupID; GameObject terrainGroup = new GameObject(groupName); TerrainGroup groupComp = terrainGroup.AddComponent <TerrainGroup>(); terrainGroup.transform.position = m_Settings.StartPosition; Heightmap globalHeightmap = null; Undo.RegisterCreatedObjectUndo(terrainGroup, "Create terrain"); // heightmap offset if (m_Settings.UseGlobalHeightmap) { byte[] rawData = File.ReadAllBytes(m_Settings.GlobalHeightmapPath); globalHeightmap = new Heightmap(rawData, m_Settings.FlipMode); tileOffsetSource = new Vector2Int(globalHeightmap.Width / m_Settings.TilesX, globalHeightmap.Height / m_Settings.TilesZ); } else { tileOffsetSource = tileResolution; } for (int x = 0; x < m_Settings.TilesX; x++, tileOffset.x += tileOffsetSource.x, tilePosition.x += tileResolution.x) { tileOffset.y = 0; tilePosition.z = m_Settings.StartPosition.z; for (int y = 0; y < m_Settings.TilesZ; y++, tileOffset.y += tileOffsetSource.y, tilePosition.z += tileResolution.y) { EditorUtility.DisplayProgressBar("Creating terrains", string.Format("Updating terrain tile ({0}, {1})", x, y), ((float)tileIndex / tileCount)); TerrainData terrainData = new TerrainData(); terrainData.alphamapResolution = m_Settings.ControlTextureResolution; terrainData.baseMapResolution = m_Settings.BaseTextureResolution; terrainData.SetDetailResolution(m_Settings.DetailResolution, m_Settings.DetailResolutionPerPatch); GameObject newGO = Terrain.CreateTerrainGameObject(terrainData); Terrain newTerrain = newGO.GetComponent <Terrain>(); newTerrain.groupingID = m_Settings.GroupID; newTerrain.allowAutoConnect = m_Settings.AutoConnect; newTerrain.drawInstanced = m_Settings.DrawInstanced; newTerrain.heightmapPixelError = m_Settings.PixelError; newTerrain.basemapDistance = m_Settings.BaseMapDistance; if (m_Settings.MaterialOverride != null) { newTerrain.materialTemplate = m_Settings.MaterialOverride; #if UNITY_2019_2_OR_NEWER #else newTerrain.materialType = Terrain.MaterialType.Custom; #endif } string terrainName = $"Terrain_{x}_{y}";; if (m_Settings.EnableGuid) { Guid newGuid = Guid.NewGuid(); terrainName = $"Terrain_{x}_{y}_{newGuid}"; } newGO.name = terrainName; newTerrain.transform.position = tilePosition; newTerrain.transform.SetParent(terrainGroup.transform); // import height if (m_Settings.HeightmapMode == Heightmap.Mode.Global && globalHeightmap != null) { Heightmap tileHeightmap = GetTileHeightmapFromGlobalHeightmap(globalHeightmap, tileOffset); tileHeightmap.ApplyTo(newTerrain); } if (m_Settings.HeightmapMode == Heightmap.Mode.Tiles || m_Settings.HeightmapMode == Heightmap.Mode.Batch) { if (File.Exists(m_Settings.TileHeightmapPaths[tileIndex])) { var remap = (m_Settings.HeightmapRemapMax - m_Settings.HeightmapRemapMin) / m_Settings.TerrainHeight; var baseLevel = m_Settings.HeightmapRemapMin / m_Settings.TerrainHeight; byte[] rawTileData = File.ReadAllBytes(m_Settings.TileHeightmapPaths[tileIndex]); Heightmap tileHeight = new Heightmap(rawTileData, m_Settings.FlipMode); Heightmap tileMap = new Heightmap(tileHeight, Vector2Int.zero, new Vector2Int(tileHeight.Width, tileHeight.Height), remap, baseLevel); tileMap.ApplyTo(newTerrain); } } terrains[tileIndex] = newTerrain; tileIndex++; // save terrain data asset terrainData.size = tileSize; // set terrain size after heightmap process string assetPath = $"{assetFolderPath}/{terrainName}.asset"; if (!Directory.Exists(assetFolderPath)) { Directory.CreateDirectory(assetFolderPath); } AssetDatabase.CreateAsset(terrainData, assetPath); // finally, resize height resolution if needed if (terrainData.heightmapResolution != (m_Settings.HeightmapResolution)) { ToolboxHelper.ResizeHeightmap(terrainData, (m_Settings.HeightmapResolution)); } Undo.RegisterCreatedObjectUndo(newGO, "Create terrain"); } } m_Terrains = terrains; m_CurrentGroup = terrainGroup; UpdateGroupSettings(groupComp); ToolboxHelper.CalculateAdjacencies(m_Terrains, m_Settings.TilesX, m_Settings.TilesZ); } finally { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); } }