/// <summary> /// 拆分地形 /// </summary> /// <param name="iLevel">层级(影响到左边缩进的余白)</param> private void SplitTerrains(int iLevel) { var level = iLevel; DrawMiddleGameObject( level, "地形根节点:", ref _terrainsRoot); var childCount = 0; if (!_terrainsRoot) { return; } childCount = _terrainsRoot.transform.childCount; // 若长宽地形个数不想等 if (false == UtilsTools.IsSquare(childCount)) { DrawLabel(level + 1, "地形部署长宽不相同(不是 N x N 布局)!", Color.red); } else { // 保存地形Tile尺寸 if (Math.Abs(ConfData.TileSize.x * ConfData.TileSize.y - childCount) > 0.0f) { ConfData.TileSize.x = (float)Math.Sqrt(childCount); ConfData.TileSize.y = ConfData.TileSize.x; } DrawMiddleLabel(level, "chunk拆分数:"); ++level; DrawLabel(level, "因为与到处高度图相关,拆分个数必须为2的N次幂(1~64)", Color.yellow); var lastSlicingCount = ConfData.chunkData.SlicingCount; DrawMiddleSlider( level, "个数( N x N ):", ref lastSlicingCount, 1.0f, 64); if (!UtilsTools.IsPowerOf2((int)lastSlicingCount)) { var error = string.Format("{0} 不是2的N次幂(1~64)!", (int)ConfData.chunkData.SlicingCount); DrawLabel(level + 1, error, Color.red); } else { if (Math.Abs(lastSlicingCount - ConfData.chunkData.SlicingCount) > 0.0f) { // 有变化贼,晴空已有数据 Settings.Clear(); ConfData.chunkData.SlicingCount = lastSlicingCount; // 清空Debug用绘制节点 ClearDebugNode(); // 层级预览信息清空 _layerPreviewTitles.Clear(); _layerPreviewSelected.Clear(); } // 分界线 DrawLongLabel(0, "---------------"); DrawSingleLongToggle(level, "是否预览拆分边界:", _chunkBoundPreviewVisiable, delegate(bool iValue) { _chunkBoundPreviewVisiable = iValue; }); // 选择层级 // 取得最高层级 var maxLayerLevel = GetMaxLayerLevel((int)ConfData.chunkData.SlicingCount); // 层级菜单标题 if (0 >= _layerPreviewSelected.Count) { for (var l = 0; l <= maxLayerLevel; ++l) { _layerPreviewTitles.Add(string.Format("层级{0}", l)); _layerPreviewSelected.Add(false); } } if (_chunkBoundPreviewVisiable) { // 各层级显示 DrawLongLabel(level + 1, string.Format("当前拆分数可分 {0} 层:", maxLayerLevel + 1)); DrawMiddleMultiplyToggle(level + 2, _layerPreviewTitles.ToArray(), _layerPreviewSelected.ToArray(), delegate(int l, bool iSelected) { _layerPreviewSelected[l] = iSelected; if (!iSelected) { ClearDebugNode(l); } }); // 显示颜色设定 var flg = false; for (var l = 0; l <= maxLayerLevel; ++l) { if (!_layerPreviewSelected[l]) { continue; } flg = true; } if (flg) { var layerPreview = ConfData.chunkData.Preview; DrawLongLabel(level + 3, "颜色设定:"); DrawMiddleColor(level + 4, "边色", layerPreview.edgeColor, delegate(Color iColor) { layerPreview.edgeColor = iColor; // 重置所有边的颜色 UtilsDraw.ResetAllCylinderColor(iColor, (int)DrawType.TerrainChunkCylinder); }); DrawMiddleColor(level + 4, "顶点色", layerPreview.vertexColor, delegate(Color iColor) { layerPreview.vertexColor = iColor; // 重置所有边的颜色 UtilsDraw.ResetAllVertexColor(iColor, (int)DrawType.TerrainChunkVertex); }); DrawMiddleSlider(level + 4, "缩放", layerPreview.Scale, delegate(float iValue) { layerPreview.Scale = iValue; UtilsDraw.ResetAllBoundsPreviewScale( iValue, (int)DrawType.TerrainChunkCylinder | (int)DrawType.TerrainChunkVertex); }, 1.0f, 50.0f); --level; } // 遍历根节点并取得包围盒 if (null == _terrainsRoot) { return; } // 基准原点:子节点中最小的点为为基准原点(既:最左最前的为第一块地形Tile) // 其他的地形都以该地形位置准排布 var baseOriginPos = GetOriginPosOfTerrainsFromTiles(_terrainsRoot.transform); var terrainTileSize = Vector3.zero; for (var i = 0; i < _terrainsRoot.transform.childCount; ++i) { var child = _terrainsRoot.transform.GetChild(i); if (null == child) { continue; } if (false == child.gameObject.activeInHierarchy) { continue; } // 地形Tile尺寸 if (Vector3.zero.Equals(terrainTileSize)) { terrainTileSize = TerrainsSettings.GetTerrainSize(child.gameObject); } // Tile Index var tileIndex = GetTerrainTileIndexByPos( baseOriginPos, child.transform.position, terrainTileSize); // 按照层级生成解析用的地形层级数据 for (var layerIndex = 0; layerIndex <= maxLayerLevel; ++layerIndex) { // 当前层级的chunk尺寸 var layerChunkSize = TerrainsSettings.GetTerrainChunkSize( terrainTileSize, maxLayerLevel, layerIndex); // 拆分当前层级的chunk数据 Settings.ParserTerrainTileData( tileIndex, layerChunkSize, maxLayerLevel, layerIndex); } for (var l = 0; l <= maxLayerLevel; ++l) { if (!_layerPreviewSelected[l]) { continue; } // 取得当前层级的chunk信息 var chunks = Settings.GetChunkData(l); if (null == chunks || 0 >= chunks.Count) { continue; } var bounds = new List <Bounds>(); // 以莫顿码为chunk索引 var chunksIndex = new List <int>(); foreach (var chunk in chunks) { bounds.Add(chunk.Bounds); chunksIndex.Add((int)chunk.Morton); } // 绘制Chunks包围盒 var layerPreview = ConfData.chunkData.Preview; if (null == layerPreview) { continue; } UtilsDraw.DrawChunkBounds( bounds.ToArray(), chunksIndex.ToArray(), child.transform, layerPreview.edgeColor, layerPreview.vertexColor, layerPreview.Scale, l); } } Settings.AutoSort(); } else { ClearDebugNode(); } DrawLongLabel(0, "---------------"); DrawLongLabel(0, "拆分设定:"); DrawLongLabel(1, "数据导入/导出目录:"); DrawLabel(2, string.Format("Chunk : {0}", Settings.ChunkDataDir), Color.green); DrawLabel(2, string.Format("预制体 : {0}", Settings.PrefabsDataDir), Color.green); DrawSingleMiddleToggle(1, "仅处理静态物体:", ConfData.chunkData.StaticOnly, delegate(bool iValue) { ConfData.chunkData.StaticOnly = iValue; }); // 地形导出层级 DrawSelectList(1, "地形导出层级:", _layerPreviewTitles.ToArray(), ref _exportLayerLevel); // 预制体导出深度 DrawMiddleSlider(1, "预制体导出深度:", ConfData.chunkData.PrefabsExportDepthLimit, delegate(float iValue) { ConfData.chunkData.PrefabsExportDepthLimit = (int)iValue; }, 1.0f, 15.0f); DrawSingleButton(0, "拆分场景", delegate() { // 显示处理进度条 ProgressBarStart("拆分地形", "开始拆分..."); // Chunk导出目录检测 var dirInfo = new DirectoryInfo(Settings.ChunkDataDir); UtilsTools.CheckAndCreateDirByFullDir(dirInfo.FullName); // 清空保存目录,但不删除目录本身 UtilsTools.ClearDirectory(TerrainsSettings.DataBaseDir, false); // 遍历根节点并取得包围盒 if (null == _terrainsRoot) { return; } // 基准原点:子节点中最小的点为为基准原点(既:最左最前的为第一块地形Tile) // 其他的地形都以该地形位置准排布 var baseOriginPos = GetOriginPosOfTerrainsFromTiles(_terrainsRoot.transform); var terrainTileSize = Vector3.zero; var maxCount = _terrainsRoot.transform.childCount * ConfData.chunkData.SlicingCount * ConfData.chunkData.SlicingCount; var progressCount = 0; for (var i = 0; i < _terrainsRoot.transform.childCount; ++i) { var child = _terrainsRoot.transform.GetChild(i); if (null == child) { continue; } if (false == child.gameObject.activeInHierarchy) { continue; } // 地形Tile尺寸 if (Vector3.zero.Equals(terrainTileSize)) { terrainTileSize = TerrainsSettings.GetTerrainSize(child.gameObject); } // Tile Index var tileIndex = GetTerrainTileIndexByPos( baseOriginPos, child.transform.position, terrainTileSize); // 拆分地形 TerrainsSplit.Instance.SplitTerrains( Settings.ChunkDataDir, child.gameObject, tileIndex, maxLayerLevel, maxLayerLevel - _exportLayerLevel, delegate(string iStatusTxt, bool iStatusCount) { if (iStatusCount) { ++progressCount; } // 计算进度 var progress = progressCount / maxCount; ProgressBarUpdate(iStatusTxt, progress); this.Info("SplitTerrains:({0}) {1}", progress, iStatusTxt); }); } // 初始化地形拆分用的预制体信息 TerrainsSplit.Instance.InitPrefabsInfo( ConfData.chunkData.StaticOnly, ConfData.chunkData.PrefabsExportDepthLimit); ProgressBarUpdate( "地形拆分成功", 1.0f); // 到处此次地形拆分配置信息 TerrainsSettings.GetInstance().ExportBySceneName(CurSceneName); ProgressBarClear(); // 刷新 AssetDatabase.Refresh(); }, Color.yellow); } } }
/// <summary> /// 新建地形 /// </summary> /// <param name="iLevel">层级(影响到左边缩进的余白)</param> private void NewTerrains(int iLevel) { var level = iLevel; ++level; DrawLongLabel(level, "地形尺寸设定:"); ++level; { DrawMiddleSlider( level, "宽(X方向):", ref ConfData.tileData.TerrainSize.x, 128.0f, 1024.0f); if (!UtilsTools.IsPowerOf2((int)ConfData.tileData.TerrainSize.x)) { var error = string.Format("{0} 不是2的N次幂(2~16)!", (int)ConfData.tileData.TerrainSize.x); DrawLabel(level + 1, error, Color.red); } } { DrawMiddleSlider( level, "长(Z方向):", ref ConfData.tileData.TerrainSize.z, 128.0f, 1024.0f); if (!UtilsTools.IsPowerOf2((int)ConfData.tileData.TerrainSize.z)) { var error = string.Format("{0} 不是2的N次幂(2~16)!", (int)ConfData.tileData.TerrainSize.z); DrawLabel(level + 1, error, Color.red); } } { DrawMiddleSlider( level, "高(Y方向):", ref ConfData.tileData.TerrainSize.y, 128.0f, 1024.0f); if (!UtilsTools.IsPowerOf2((int)ConfData.tileData.TerrainSize.y)) { var error = string.Format("{0} 不是2的N次幂(2~16)!", (int)ConfData.tileData.TerrainSize.y); DrawLabel(level + 1, error, Color.red); } } // 分界线 DrawLongLabel(0, "---------------"); --level; // 地形数量 DrawLongLabel(level, "地形数量(布局):"); ++level; DrawMiddleSlider( level, "数量(x):", ref ConfData.TileSize.x, 1.0f, 16.0f); DrawMiddleSlider( level, "数量(z):", ref ConfData.TileSize.y, 1.0f, 16.0f); // 基础地形 DrawMiddleTerrain(level, "基础地形:", ref ConfData.tileData.Data); --level; DrawSingleButton(0, "初始化地形", delegate() { // 自动生成Chunk AutoCreateTerrains(ConfData.tileData); }, Color.yellow); }