Ejemplo n.º 1
0
        //---------------------------------------------------------------------------------------
        // OnGUI
        //---------------------------------------------------------------------------------------
        void OnGUI()
        {
            // 场景名字
            var    scenePath = EditorApplication.currentScene;
            string sceneName = UtilityTools.GetFileName(scenePath);

            if (_sceneName != sceneName)
            {
                _sceneName = sceneName;
                LoadSettings();
            }

            EditorGUI.BeginChangeCheck();

            // 树列表
            EditorGUILayout.LabelField("场景树");
            for (int i = 0; i < _settings.trees.Count; ++i)
            {
                DrawSeparator(1, 1);

                var tree = _settings.trees[i];
                tree.name              = EditorGUILayout.TextField("名称", tree.name);
                tree.splitType         = (SceneTreeSplitType)EditorGUILayout.EnumPopup("划分类型", tree.splitType);
                tree.objType           = (SceneTreeObjType)EditorGUILayout.EnumPopup("对象类型", tree.objType);
                tree.maxDepth          = EditorGUILayout.IntField("最大层数", tree.maxDepth);
                tree.viewDistance      = EditorGUILayout.FloatField("可视距离", tree.viewDistance);
                tree.maxItemBoundsSize = EditorGUILayout.FloatField("最大物体大小", tree.maxItemBoundsSize);
            }

            // 导出
            GUILayout.FlexibleSpace();

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            _recovertScene = GUILayout.Toggle(_recovertScene, "导出完是否恢复");
            _backScene     = GUILayout.Toggle(_backScene, "备份场景");
            _compressScene = GUILayout.Toggle(_compressScene, "压缩场景");
            _compressRes   = GUILayout.Toggle(_compressRes, "压缩资源");
            GUILayout.EndHorizontal();
            GUILayout.Space(20);

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            if (GUILayout.Button("检查设置", GUILayout.Width(100)))
            {
                int settingsObjTypeFlag = 0;
                SceneTree.CheckSettings(_settings.trees, out settingsObjTypeFlag);
            }

            else if (GUILayout.Button("导出资源", GUILayout.Width(100)))
            {
                BuildScene(_backScene, true, _compressScene, _compressRes);
            }

            else
            {
                GUILayout.EndHorizontal();
                GUILayout.Space(10);
                if (EditorGUI.EndChangeCheck())
                {
                    SaveSettings();
                }
            }
        }
Ejemplo n.º 2
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());
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 生成场景
        /// </summary>
        void BuildScene(bool exportScene, bool exportRes, bool compressScene, bool compressRes)
        {
            // 先保存场景
            EditorApplication.SaveScene();

            // 场景名字
            var    scenePath = EditorApplication.currentScene;
            string sceneName = UtilityTools.GetFileName(scenePath);

            // 导出目录
            var exportPath = UtilityTools.GenResExportPath(string.Format("scene/{0}", sceneName), sceneName);
            var exportDir  = Path.GetDirectoryName(exportPath);

            // 删除目录
            if (exportRes && exportScene)
            {
                Directory.Delete(exportDir, true);
            }

            // 创建目录
            if (!Directory.Exists(exportDir))
            {
                Directory.CreateDirectory(exportDir);
            }

            /// 开始处理数据
            try
            {
                do
                {
                    AssetsBackuper.inst.Clear();
                    if (exportScene)
                    {
                        var outputDir = EditorUtil.GetSceneOutputPath(null);
                        AssetDatabase.DeleteAsset(outputDir);
                        var outputPath = EditorUtil.GetSceneOutputPath(string.Format("{0}.unity", sceneName));
                        EditorApplication.SaveScene(outputPath);
                    }

                    // 树结构
                    var meshColliders = new List <MeshCollider>();
                    var trees         = SceneTree.Build(_settings.trees, meshColliders);
                    if (null == trees)
                    {
                        break;
                    }
                    SaveSettings();
                    SceneTree.Export(trees, meshColliders, exportRes, compressRes);

                    // 准备导出
                    EditorApplication.SaveScene();
                    AssetDatabase.SaveAssets();

                    if (exportScene)
                    {
                        ResExportUtil.ExportCurrentScene(true, compressScene);
                    }
                }while(false);
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                AssetsBackuper.inst.Recover();
                AssetDatabase.SaveAssets();
            }

            finally
            {
                // 还原修改过的资源和场景
                if (_recovertScene)
                {
                    AssetsBackuper.inst.Recover();
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                    EditorApplication.OpenScene(scenePath);
                    Resources.UnloadUnusedAssets();
                }
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// 构造
 /// </summary>
 /// <param name="tree"></param>
 /// <param name="depth"></param>
 public SceneTreeNode(SceneTree tree, int depth)
 {
     _tree  = tree;
     _depth = depth;
 }