/// <summary> /// 生成 /// </summary> public static SceneTree[] Build(List <SceneTreeSettings> settings, List <MeshCollider> meshColliders) { // 检查设置 int settingsObjTypeFlag = 0; if (!CheckSettings(settings, out settingsObjTypeFlag)) { return(null); } // 收集GameObject并计算包围盒 var gos = (GameObject[])GameObject.FindObjectsOfType <GameObject>(); var items = new List <SceneItem>(); Bounds sceneBounds = new Bounds(); // 检测自动计算场景包围盒 bool bCalculateSceneBound = false; var ters = GameObject.FindGameObjectsWithTag("Terrain"); if (ters == null || ters.Length <= 0) { bCalculateSceneBound = true; } var otherColliders = new List <Collider>(); var sb = new StringBuilder(); sb.AppendFormat("Start build {0} items...\n", gos.Length); for (int i = 0; i < gos.Length; ++i) { var go = gos[i]; EditorUtility.DisplayProgressBar(string.Format("Build items({0}/{1})", i + 1, gos.Length), go.name, (float)(i + 1) / gos.Length); if (UtilityTools.IsEditorOnly(go)) { continue; } // 包围盒 int objTypeFlag = 0; otherColliders.Clear(); var bounds = GetBounds(go, otherColliders, meshColliders, out objTypeFlag); if (objTypeFlag == 0) { continue; } var size = Vector3.Distance(bounds.min, bounds.max); if (size < MathUtil.fEpsilon) { Debug.LogErrorFormat("Invalid bounds of {0}!", go.name); continue; } /// 场景中没有表示地形,自动累计 if (bCalculateSceneBound) { sceneBounds.Encapsulate(bounds); } else { // 使用地形包围盒生成场景包围盒 if (go.CompareTag("Terrain")) { go.layer = LayerDefine.Terrain; if (sceneBounds.size.x < MathUtil.fEpsilon) { sceneBounds = bounds; } else { sceneBounds.Encapsulate(bounds); } } } // 没有交集 if ((settingsObjTypeFlag & objTypeFlag) == 0) { continue; } // 加入列表 var item = new SceneItem(); item.go = go; item.colliders = otherColliders.ToArray(); item.bounds = bounds; item.radius = size * 0.5f; item.size = size; item.objTypeFlag = objTypeFlag; item.cfg = go.GetComponent <EditorSceneObject>(); items.Add(item); } EditorUtility.ClearProgressBar(); sb.Append("Build items complete."); Debug.Log(sb.ToString()); sb.Length = 0; var meshColliderCount = meshColliders.Count; sb.AppendFormat("MeshCollider count is {0}", meshColliderCount); Debug.Log(sb.ToString()); // 场景包围盒大小为0 if (sceneBounds.size.x < MathUtil.fEpsilon) { Debug.LogError("Build scene bounds failed!"); return(null); } // 列表 var itemCount = items.Count; var treeItems = new List <SceneItem> [settings.Count]; for (int i = 0; i < treeItems.Length; ++i) { treeItems[i] = new List <SceneItem>(); } // 把对象分别填充到每棵树的列表中 for (int i = 0, ni = 0, ci = items.Count, cn = ci; i < ci; ++i, ++ni) { var item = items[i]; EditorUtility.DisplayProgressBar(string.Format("Insert items to tree({0}/{1})", ni + 1, cn), item.go.name, (float)(ni + 1) / cn); for (int j = 0, cj = settings.Count; j < cj; ++j) { var setting = settings[j]; var list = treeItems[j]; if ((item.objTypeFlag & (1 << (int)setting.objType)) == 0) { continue; } if (SceneTreeObjType.Renderer == setting.objType) { if (null != item.cfg && !string.IsNullOrEmpty(item.cfg.specSceneTree)) { if (item.cfg.specSceneTree == setting.name) { list.Add(item); items.RemoveAt(i--); --ci; break; } continue; } // 只包含指定名字对象 if (setting.name == "grass") { continue; } // 大小 if (item.size < setting.maxItemBoundsSize) { list.Add(item); items.RemoveAt(i--); --ci; break; } continue; } // 碰撞体 if (SceneTreeObjType.Collider == setting.objType) { list.Add(item); if (item.objTypeFlag == (1 << (int)setting.objType)) { items.RemoveAt(i--); --ci; } continue; } } } EditorUtility.ClearProgressBar(); // 剩下的,放到最后一个节点 if (items.Count > 0) { Debug.LogWarningFormat("{0} items can not add to trees!", items.Count); treeItems[settings.Count - 1].AddRange(items); items.Clear(); } // 生成 var trees = new List <SceneTree>(); for (int i = 0; i < treeItems.Length; ++i) { var setting = settings[i]; EditorUtility.DisplayProgressBar(string.Format("SplitScene({0}/{1})", i + 1, treeItems.Length), setting.name, (float)(i + 1) / treeItems.Length); var list = treeItems[i]; if (list.Count < 1) { continue; } var tree = new SceneTree(setting); tree.SplitScene(list, sceneBounds); trees.Add(tree); } EditorUtility.ClearProgressBar(); // 打印日志 sb.Length = 0; var scenePath = EditorApplication.currentScene; if (string.IsNullOrEmpty(scenePath)) { scenePath = "Untitled"; } sb.AppendFormat("Scene build complete. [{0}]\n", scenePath); sb.Append("---------------------------------------------------------------\n"); sb.AppendFormat("TreeCount[{0}]\n", trees.Count); sb.AppendFormat("ItemCount[{0}]\n", itemCount); Debug.Log(sb.ToString()); for (int i = 0; i < trees.Count; ++i) { var tree = trees[i]; if (null != tree) { tree.LogTreeInfo(); } } return(trees.ToArray()); }