Exemple #1
0
        /// <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());
        }