/// <summary>
        /// Bakes a combined mesh.
        /// </summary>
        /// <param name="mom"></param>
        /// <param name="so">This is needed to work around a Unity bug where UnpackPrefabInstance corrupts
        /// a SerializedObject. Only needed for bake into prefab.</param>
        public static bool bake(MeshBakerCommon mom, ref SerializedObject so)
        {
            bool createdDummyTextureBakeResults = false;
            bool success = false;

            try
            {
                if (mom.meshCombiner.outputOption == OutputOptions.bakeIntoSceneObject ||
                    mom.meshCombiner.outputOption == OutputOptions.bakeIntoPrefab)
                {
                    success = MeshCombinerEditorFunctions.BakeIntoCombined(mom, out createdDummyTextureBakeResults, ref so);
                }
                else
                {
                    //bake meshes in place
                    if (mom is MeshCombinerEntrance)
                    {
                        ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust;
                        if (!MeshBakerRoot.DoCombinedValidate(mom, ObjsToCombineTypes.prefabOnly, new EditorMethods(), vl))
                        {
                            return(false);
                        }

                        List <GameObject> objsToMesh = mom.GetObjectsToCombine();
                        ////success = MB3_BakeInPlace.BakeMeshesInPlace((MeshCombineHandler)((MeshCombinerEntrance)mom).meshCombiner, objsToMesh, mom.bakeAssetsInPlaceFolderPath, mom.clearBuffersAfterBake, updateProgressBar);
                    }
                    else
                    {
                        //多网格合并无法 Bake In Place
                        Debug.LogError("Multi-mesh Baker components cannot be used for Bake In Place. Use an ordinary Mesh Baker object instead.");
                    }
                }
                mom.meshCombiner.CheckIntegrity();
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                if (createdDummyTextureBakeResults && mom.textureBakeResults != null)
                {
                    MeshBakerUtility.Destroy(mom.textureBakeResults);
                    mom.textureBakeResults = null;
                }
                EditorUtility.ClearProgressBar();
            }
            return(success);
        }
        /// <summary>
        /// 构建预制体
        /// </summary>
        /// <param name="mom"></param>
        /// <param name="so"></param>
        public static void RebuildPrefab(MeshBakerCommon mom, ref SerializedObject so)
        {
            GameObject prefabRoot = mom.resultPrefab;
            GameObject rootGO     = (GameObject)PrefabUtility.InstantiatePrefab(prefabRoot);

            SceneBakerUtilityInEditor.UnpackPrefabInstance(rootGO, ref so);

            //remove all renderer childeren of rootGO
            Renderer[] rs = rootGO.GetComponentsInChildren <Renderer>();
            for (int i = 0; i < rs.Length; i++)
            {
                if (rs[i] != null && rs[i].transform.parent == rootGO.transform)
                {
                    MeshBakerUtility.Destroy(rs[i].gameObject);
                }
            }

            if (mom is MeshCombinerEntrance)
            {
                MeshCombinerEntrance entrance = (MeshCombinerEntrance)mom;
                MeshCombineHandler   mbs      = (MeshCombineHandler)entrance.meshCombiner;
                MeshCombineHandler.BuildPrefabHierarchy(mbs, rootGO, mbs.GetMesh());
            }
            ////else if (mom is MB3_MultiMeshBaker)
            ////{
            ////    MB3_MultiMeshBaker mmb = (MB3_MultiMeshBaker)mom;
            ////    MB3_MultiMeshCombiner mbs = (MB3_MultiMeshCombiner)mmb.meshCombiner;
            ////    for (int i = 0; i < mbs.meshCombiners.Count; i++)
            ////    {
            ////        MB3_MeshCombinerSingle.BuildPrefabHierarchy(mbs.meshCombiners[i].combinedMesh, rootGO, mbs.meshCombiners[i].combinedMesh.GetMesh(), true);
            ////    }
            ////}
            else
            {
                Debug.LogError("MeshCombiner合并器类型错误");
            }

            //保存预制体
            string prefabPth = AssetDatabase.GetAssetPath(prefabRoot);

            SceneBakerUtilityInEditor.ReplacePrefab(rootGO, prefabPth, ReplacePrefabOption.connectToPrefab);
            if (mom.meshCombiner.renderType != RendererType.skinnedMeshRenderer)
            {
                // For Skinned meshes, leave the prefab instance in the scene so source game objects can moved into the prefab.
                UnityEditor.Editor.DestroyImmediate(rootGO);
            }
        }
        /// <summary>
        /// 创建图集
        /// </summary>
        public static void CreateAtlases(List <GameObject> GameObjectsToCombine,
                                         bool saveAtlasesAsAssets = false)
        {
            try
            {
                combineData.ResultAtlasesAndRects = null;
                combineData.saveAtlasesAsAssets   = saveAtlasesAsAssets;
                //--- 1、合并前检测
                if (!ValidateCombineGameObject(GameObjectsToCombine))
                {
                    return;
                }

                //材质验证
                if (combineData.DoMultiMaterial)
                {
                    if (!_ValidateResultMaterials(GameObjectsToCombine, combineData.ResultMaterials))
                    {
                        return;
                    }
                }
                else
                {
                    if (!ValidateSingleResultMaterial(GameObjectsToCombine, combineData.ResultMaterial))
                    {
                        return;
                    }
                }


                ////--- 2、初始化存储合并结果的数据结构
                int numResults = 1;
                if (combineData.DoMultiMaterial)
                {
                    numResults = combineData.ResultMaterials.Length;
                }

                combineData.ResultAtlasesAndRects = new AtlasesAndRects[numResults];
                for (int i = 0; i < combineData.ResultAtlasesAndRects.Length; i++)
                {
                    combineData.ResultAtlasesAndRects[i] = new AtlasesAndRects();
                }

                //--- 3、开始合并材质(单个,多个)
                for (int i = 0; i < combineData.ResultAtlasesAndRects.Length; i++)
                {
                    Material        resultMat;
                    List <Material> sourceMats;
                    if (combineData.DoMultiMaterial)
                    {
                        sourceMats = combineData.ResultMaterials[i].sourceMaterials;
                        resultMat  = combineData.ResultMaterials[i].combinedMaterial;
                        combineData.fixOutOfBoundsUVs = combineData.ResultMaterials[i].considerMeshUVs;
                    }
                    else
                    {
                        resultMat  = combineData.ResultMaterial;
                        sourceMats = null;  //为空则为全部合并
                    }

                    CombineTexturesIntoAtlases(combineData.ResultAtlasesAndRects[i],
                                               resultMat,
                                               GameObjectsToCombine,
                                               sourceMats,
                                               null);
                }

                //--- 4、TextureBakeResults 保存合并结果
                //unpackMat2RectMap(textureBakeResults);
                //textureBakeResults.doMultiMaterial = _doMultiMaterial;
                //if (_doMultiMaterial)
                //{
                //    textureBakeResults.resultMaterials = resultMaterials;
                //}
                //else
                //{
                //    MultiMaterial[] resMats = new MultiMaterial[1];
                //    resMats[0] = new MultiMaterial();
                //    resMats[0].combinedMaterial = _resultMaterial;
                //    resMats[0].considerMeshUVs = _fixOutOfBoundsUVs;
                //    resMats[0].sourceMaterials = new List<Material>();
                //    for (int i = 0; i < textureBakeResults.materialsAndUVRects.Length; i++)
                //    {
                //        resMats[0].sourceMaterials.Add(textureBakeResults.materialsAndUVRects[i].material);
                //    }
                //    textureBakeResults.resultMaterials = resMats;
                //}

                ////--- 5、传递合并结果到 MeshCombiner
                //MeshBakerCommon[] mb = GetComponentsInChildren<MeshBakerCommon>();
                //for (int i = 0; i < mb.Length; i++)
                //{
                //    mb[i].textureBakeResults = textureBakeResults;
                //}
                //coroutineResult.isFinished = true;

                ////--- 6、合并材质结束回调
                //if (coroutineResult.success && onBuiltAtlasesSuccess != null)
                //{
                //    onBuiltAtlasesSuccess();
                //}
                //if (!coroutineResult.success && onBuiltAtlasesFail != null)
                //{
                //    onBuiltAtlasesFail();
                //}
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                if (saveAtlasesAsAssets)
                { //Atlases were saved to project so we don't need these ones
                    if (combineData.ResultAtlasesAndRects != null)
                    {
                        for (int j = 0; j < combineData.ResultAtlasesAndRects.Length; j++)
                        {
                            AtlasesAndRects mAndA = combineData.ResultAtlasesAndRects[j];
                            if (mAndA != null && mAndA.atlases != null)
                            {
                                for (int i = 0; i < mAndA.atlases.Length; i++)
                                {
                                    if (mAndA.atlases[i] != null)
                                    {
                                        //if (editorMethods != null)
                                        //{
                                        //    editorMethods.Destroy(mAndA.atlases[i]);
                                        //}
                                        //else
                                        //{
                                        MeshBakerUtility.Destroy(mAndA.atlases[i]);
                                        //}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        ///  Bakes a combined mesh.
        ///  如果是从Inspector代码中调用的,则传入该组件的SerializedObject
        ///  对于“烘焙到预制”可能会损坏SerializedObject。这是必需的
        /// </summary>
        public static bool BakeIntoCombined(MeshBakerCommon mom, out bool createdDummyTextureBakeResults, ref SerializedObject so)
        {
            OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;

            createdDummyTextureBakeResults = false;
            if (prefabOrSceneObject != OutputOptions.bakeIntoPrefab && prefabOrSceneObject != OutputOptions.bakeIntoSceneObject)
            {
                Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject");
                return(false);
            }

            //从父物体获得 贴图合并组件及其贴图合并结果 Asset
            TextureCombineEntrance tb = mom.GetComponentInParent <TextureCombineEntrance>();

            if (mom.textureBakeResults == null && tb != null)
            {
                mom.textureBakeResults = tb.textureBakeResults;
            }
            //贴图合并结果为空时,则创建
            if (mom.textureBakeResults == null)
            {
                if (_OkToCreateDummyTextureBakeResult(mom))
                {
                    createdDummyTextureBakeResults = true;
                    List <GameObject> gos = mom.GetObjectsToCombine();
                    if (mom.GetNumObjectsInCombined() > 0)
                    {
                        if (mom.clearBuffersAfterBake)
                        {
                            mom.ClearMesh();
                        }
                        else
                        {
                            Debug.LogError("'Texture Bake Result' must be set to add more objects to a combined mesh that " +
                                           "already contains objects. Try enabling 'clear buffers after bake'");
                            return(false);
                        }
                    }
                    mom.textureBakeResults = TextureBakeResults.CreateForMaterialsOnRenderer(
                        gos.ToArray(),
                        mom.meshCombiner.GetMaterialsOnTargetRenderer());
                    Debug.Log("'Texture Bake Result' was not set. " +
                              "Creating a temporary one. Each material will be mapped to a separate submesh.");
                }
            }

            //合并检测
            ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust;

            if (!MeshBakerRoot.DoCombinedValidate(mom, ObjsToCombineTypes.sceneObjOnly, new EditorMethods(), vl))
            {
                return(false);
            }

            //检测空预制体资源是否已创建
            if (prefabOrSceneObject == OutputOptions.bakeIntoPrefab &&
                mom.resultPrefab == null)
            {
                Debug.LogError("Need to set the Combined Mesh Prefab field. " +
                               "Create a prefab asset, drag an empty game object into it, and drag it to the 'Combined Mesh Prefab' field.");
                return(false);
            }

            if (mom.meshCombiner.resultSceneObject != null &&
                (SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.modelPrefab ||
                 SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.prefab))
            {
                Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field.");
                mom.meshCombiner.resultSceneObject = null;
            }

            mom.ClearMesh();

            //合并
            if (mom.AddDeleteGameObjects(mom.GetObjectsToCombine().ToArray(), null, false))
            {
                mom.Apply(UnwrapUV2);
                if (createdDummyTextureBakeResults)
                {
                    //临时合并的贴图
                    Debug.Log(String.Format("Successfully baked {0} meshes each material is mapped to its own submesh.",
                                            mom.GetObjectsToCombine().Count));
                }
                else
                {
                    Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count));
                }


                if (prefabOrSceneObject == OutputOptions.bakeIntoSceneObject)
                {
                    PrefabType pt = SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject);
                    if (pt == PrefabType.prefab || pt == PrefabType.modelPrefab)
                    {
                        Debug.LogError("Combined Mesh Object is a prefab asset. " +
                                       "If output option bakeIntoSceneObject then this must be an instance in the scene.");
                        return(false);
                    }
                }
                else if (prefabOrSceneObject == OutputOptions.bakeIntoPrefab)
                {
                    string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
                    if (prefabPth == null || prefabPth.Length == 0)
                    {
                        Debug.LogError("无法保存,合并游戏物体并非磁盘上的资源。");
                        return(false);
                    }
                    string baseName    = Path.GetFileNameWithoutExtension(prefabPth);
                    string folderPath  = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 7);
                    string newFilename = folderPath + baseName + "-mesh";

                    //保存网格资源
                    SaveMeshsToAssetDatabase(mom, folderPath, newFilename);

                    if (mom.meshCombiner.renderType == RendererType.skinnedMeshRenderer)
                    {
                        Debug.LogWarning("Render type is skinned mesh renderer. " +
                                         "Can't create prefab until all bones have been added to the combined mesh object " + mom.resultPrefab +
                                         " Add the bones then drag the combined mesh object to the prefab.");
                    }
                    //构建 Prefab
                    RebuildPrefab(mom, ref so);

                    MeshBakerUtility.Destroy(mom.meshCombiner.resultSceneObject);
                }
                else
                {
                    Debug.LogError("合并输出类型出错");
                    return(false);
                }
            }
            else
            {
                //加入合并失败
                if (mom.clearBuffersAfterBake)
                {
                    mom.meshCombiner.ClearBuffers();
                }
                if (createdDummyTextureBakeResults)
                {
                    MeshBakerUtility.Destroy(mom.textureBakeResults);
                }
                return(false);
            }

            //清除缓存数据
            if (mom.clearBuffersAfterBake)
            {
                mom.meshCombiner.ClearBuffers();
            }
            //临时Texture
            if (createdDummyTextureBakeResults)
            {
                MeshBakerUtility.Destroy(mom.textureBakeResults);
            }
            return(true);
        }