void ApplySettingsToTerrains(Terrain[] terrains, string errorContext = "") { int index = 0; try { bool continueEdit = true; // Only show this warning if the user has Mesh Settings enabled. if (m_Settings.EnableMeshResSettings) { var newSize = new Vector3(m_Settings.TerrainWidth, m_Settings.TerrainHeight, m_Settings.TerrainLength); foreach (var terrain in terrains) { // If any terrain has a size that's different from the specified settings, let's confirm // the action. if (terrain.terrainData.size != newSize) { var message = "Some terrains have different sizes than the settings specified. This operation will resize the terrains potentially resulting in gaps and/or overlaps."; if (string.IsNullOrEmpty(errorContext)) { continueEdit = EditorUtility.DisplayDialog("Confirm", $"{message}\nAre you sure you want to continue?", "Continue", "Cancel"); } else { continueEdit = EditorUtility.DisplayDialog("Confirm", $"1. {errorContext}\n2. {message}\n\nAre you sure you want to continue?", "Continue", "Cancel"); } break; } } } if (continueEdit) { foreach (var terrain in terrains) { EditorUtility.DisplayProgressBar("Applying settings changes on terrains", string.Format("Updating terrain tile {0}", terrain.name), ((float)index / terrains.Length)); if (m_Settings.EnableBasicSettings) { Undo.RecordObject(terrain, "Terrain property change"); terrain.groupingID = m_Settings.GroupingID; terrain.allowAutoConnect = m_Settings.AutoConnect; terrain.drawHeightmap = m_Settings.DrawHeightmap; terrain.drawInstanced = m_Settings.DrawInstanced; terrain.heightmapPixelError = m_Settings.PixelError; terrain.basemapDistance = m_Settings.BaseMapDistance; terrain.shadowCastingMode = m_Settings.ShadowCastingMode; terrain.materialTemplate = m_Settings.MaterialTemplate; terrain.reflectionProbeUsage = m_Settings.ReflectionProbeUsage; #if UNITY_2019_2_OR_NEWER #else terrain.materialType = m_Settings.MaterialType; if (m_Settings.MaterialType != Terrain.MaterialType.Custom) { terrain.legacySpecular = m_Settings.LegacySpecular; terrain.legacyShininess = m_Settings.LegacyShininess; } #endif } if (m_Settings.EnableMeshResSettings) { Undo.RecordObject(terrain.terrainData, "TerrainData property change"); Vector3 size = new Vector3(m_Settings.TerrainWidth, m_Settings.TerrainHeight, m_Settings.TerrainLength); terrain.terrainData.size = size; terrain.terrainData.SetDetailResolution(m_Settings.DetailResolutaion, m_Settings.DetailResolutionPerPatch); } if (m_Settings.EnableTextureResSettings) { terrain.terrainData.baseMapResolution = m_Settings.BaseTextureResolution; if (m_Settings.AlphaMapResolution != terrain.terrainData.alphamapResolution) { ToolboxHelper.ResizeControlTexture(terrain.terrainData, m_Settings.AlphaMapResolution); } if (m_Settings.HeightMapResolution != terrain.terrainData.heightmapResolution) { ToolboxHelper.ResizeHeightmap(terrain.terrainData, m_Settings.HeightMapResolution); } } if (m_Settings.EnableTreeSettings) { Undo.RecordObject(terrain, "Terrain property change"); terrain.drawTreesAndFoliage = m_Settings.DrawTreesAndFoliage; terrain.bakeLightProbesForTrees = m_Settings.BakeLightProbesForTrees; terrain.deringLightProbesForTrees = m_Settings.DeringLightProbesForTrees; terrain.preserveTreePrototypeLayers = m_Settings.PreserveTreePrototypeLayers; terrain.detailObjectDistance = m_Settings.DetailObjectDistance; terrain.collectDetailPatches = m_Settings.CollectDetailPatches; terrain.detailObjectDensity = m_Settings.DetailObjectDensity; terrain.treeDistance = m_Settings.TreeDistance; terrain.treeBillboardDistance = m_Settings.TreeBillboardDistance; terrain.treeCrossFadeLength = m_Settings.TreeCrossFadeLength; terrain.treeMaximumFullLODCount = m_Settings.TreeMaximumFullLODCount; } if (m_Settings.EnableWindSettings) { Undo.RecordObject(terrain.terrainData, "TerrainData property change"); terrain.terrainData.wavingGrassStrength = m_Settings.WavingGrassStrength; terrain.terrainData.wavingGrassSpeed = m_Settings.WavingGrassSpeed; terrain.terrainData.wavingGrassAmount = m_Settings.WavingGrassAmount; terrain.terrainData.wavingGrassTint = m_Settings.WavingGrassTint; } index++; } } } finally { AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); } }
void ApplySettingsToTerrains(Terrain[] terrains) { int index = 0; try { foreach (var terrain in terrains) { EditorUtility.DisplayProgressBar("Applying settings changes on terrains", string.Format("Updating terrain tile {0}", terrain.name), ((float)index / terrains.Length)); if (m_Settings.EnableBasicSettings) { Undo.RecordObject(terrain, "Terrain property change"); terrain.groupingID = m_Settings.GroupingID; terrain.allowAutoConnect = m_Settings.AutoConnect; terrain.drawHeightmap = m_Settings.DrawHeightmap; terrain.drawInstanced = m_Settings.DrawInstanced; terrain.heightmapPixelError = m_Settings.PixelError; terrain.basemapDistance = m_Settings.BaseMapDistance; terrain.shadowCastingMode = m_Settings.ShadowCastingMode; terrain.materialTemplate = m_Settings.MaterialTemplate; terrain.reflectionProbeUsage = m_Settings.ReflectionProbeUsage; #if UNITY_2019_2_OR_NEWER #else terrain.materialType = m_Settings.MaterialType; if (m_Settings.MaterialType != Terrain.MaterialType.Custom) { terrain.legacySpecular = m_Settings.LegacySpecular; terrain.legacyShininess = m_Settings.LegacyShininess; } #endif } if (m_Settings.EnableMeshResSettings) { Undo.RecordObject(terrain.terrainData, "TerrainData property change"); Vector3 size = new Vector3(m_Settings.TerrainWidth, m_Settings.TerrainHeight, m_Settings.TerrainLength); terrain.terrainData.size = size; terrain.terrainData.SetDetailResolution(m_Settings.DetailResolutaion, m_Settings.DetailResolutionPerPatch); } if (m_Settings.EnableTextureResSettings) { terrain.terrainData.baseMapResolution = m_Settings.BaseTextureResolution; if (m_Settings.AlphaMapResolution != terrain.terrainData.alphamapResolution) { ToolboxHelper.ResizeControlTexture(terrain.terrainData, m_Settings.AlphaMapResolution); } if (m_Settings.HeightMapResolution != terrain.terrainData.heightmapResolution) { ToolboxHelper.ResizeHeightmap(terrain.terrainData, m_Settings.HeightMapResolution); } } if (m_Settings.EnableTreeSettings) { Undo.RecordObject(terrain, "Terrain property change"); terrain.drawTreesAndFoliage = m_Settings.DrawTreesAndFoliage; terrain.bakeLightProbesForTrees = m_Settings.BakeLightProbesForTrees; terrain.deringLightProbesForTrees = m_Settings.DeringLightProbesForTrees; terrain.preserveTreePrototypeLayers = m_Settings.PreserveTreePrototypeLayers; terrain.detailObjectDistance = m_Settings.DetailObjectDistance; terrain.collectDetailPatches = m_Settings.CollectDetailPatches; terrain.detailObjectDensity = m_Settings.DetailObjectDensity; terrain.treeDistance = m_Settings.TreeDistance; terrain.treeBillboardDistance = m_Settings.TreeBillboardDistance; terrain.treeCrossFadeLength = m_Settings.TreeCrossFadeLength; terrain.treeMaximumFullLODCount = m_Settings.TreeMaximumFullLODCount; } if (m_Settings.EnableWindSettings) { Undo.RecordObject(terrain.terrainData, "TerrainData property change"); terrain.terrainData.wavingGrassStrength = m_Settings.WavingGrassStrength; terrain.terrainData.wavingGrassSpeed = m_Settings.WavingGrassSpeed; terrain.terrainData.wavingGrassAmount = m_Settings.WavingGrassAmount; terrain.terrainData.wavingGrassTint = m_Settings.WavingGrassTint; } index++; } } finally { AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); } }
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(); } }