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();
            }
        }