예제 #1
0
        /// <summary>
        /// 查找资源的依赖,并生成默认的分组,将依赖的资源也单独打包处理
        /// </summary>
        /// <param name="isShowProgressBar"></param>
        internal static void FindAndAddAutoGroup(bool isShowProgressBar = false)
        {
            DeleteAutoGroup();

            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());
            AssetDependFinder    finder    = CreateAssetDependFinder(tagConfig, isShowProgressBar);

            Dictionary <string, int> repeatAssetDic = finder.GetRepeatUsedAssets();

            AssetBundleGroupData gData = new AssetBundleGroupData();

            gData.GroupName = AUTO_REPEAT_GROUP_NAME;
            gData.IsMain    = false;

            foreach (var kvp in repeatAssetDic)
            {
                AssetAddressData aaData = new AssetAddressData();
                aaData.AssetAddress = aaData.AssetPath = kvp.Key;
                aaData.BundlePath   = HashHelper.Hash_MD5_32(kvp.Key, false);//AssetDatabase.AssetPathToGUID(kvp.Key);
                gData.AssetDatas.Add(aaData);
            }

            if (gData.AssetDatas.Count > 0)
            {
                tagConfig.GroupDatas.Add(gData);
            }

            Util.FileUtil.SaveToBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath(), tagConfig);
        }
예제 #2
0
        internal BundlePackConfigGUI()
        {
            m_TargetContent           = new GUIContent("Build Target", "Choose target platform to build for.");
            m_CompressionContent      = new GUIContent("Compression", "Choose no compress, standard (LZMA), or chunk based (LZ4)");
            m_ForceRebuildContent     = new GUIContent("Force Rebuild", "Force rebuild the asset bundles");
            m_AppendHashContent       = new GUIContent("Append Hash", "Append the hash to the assetBundle name.");
            m_CleanBeforeBuildContent = new GUIContent("Clean Output Dir", "Delete the output dir before build");

            m_PackConfig     = Util.FileUtil.ReadFromBinary <BundlePackConfig>(BundlePackUtil.GetPackConfigPath());
            m_IsForceRebuild = m_PackConfig.BundleOptions.HasFlag(BuildAssetBundleOptions.ForceRebuildAssetBundle);
            m_IsAppendHash   = m_PackConfig.BundleOptions.HasFlag(BuildAssetBundleOptions.AppendHashToAssetBundleName);
        }
예제 #3
0
        /// <summary>
        /// 删除自动查找到的依赖的分组
        /// </summary>
        internal static void DeleteAutoGroup()
        {
            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());

            for (int i = 0; i < tagConfig.GroupDatas.Count; ++i)
            {
                if (tagConfig.GroupDatas[i].GroupName == AUTO_REPEAT_GROUP_NAME)
                {
                    tagConfig.GroupDatas.RemoveAt(i);
                    break;
                }
            }
            Util.FileUtil.SaveToBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath(), tagConfig);
        }
예제 #4
0
        /// <summary>
        /// 检查资源Address是否有重复的
        /// </summary>
        /// <returns></returns>
        public static bool IsAddressRepeat()
        {
            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());

            AssetAddressData[] datas = (from groupData in tagConfig.GroupDatas
                                        where groupData.IsMain
                                        from assetData in groupData.AssetDatas
                                        select assetData).ToArray();

            List <string> addressList = new List <string>();
            bool          isRepeat    = false;

            foreach (var data in datas)
            {
                if (addressList.IndexOf(data.AssetAddress) >= 0)
                {
                    isRepeat = true;
                    Debug.LogError($"BundlePackUtil::IsAddressRepeat->AssetAddress Repeat.address = {data.AssetAddress}");
                }
                else
                {
                    addressList.Add(data.AssetAddress);
                }
            }

            return(isRepeat);
        }
예제 #5
0
        /// <summary>
        /// 根据项目中的配置进行AB打包
        /// </summary>
        /// <param name="assetBundleManifest"></param>
        /// <param name="setting"><see cref="PackBundleSetting"/></param>
        /// <returns></returns>
        public static bool PackBundle(out AssetBundleManifest assetBundleManifest, PackBundleSetting setting)
        {
            assetBundleManifest = null;

            if (setting.UpdateConfigs)
            {
                if (!GenerateConfigs())
                {
                    return(false);
                }

                if (setting.FindDepend)
                {
                    FindAndAddAutoGroup(setting.IsShowProgressBar);
                }
                else
                {
                    DeleteAutoGroup();
                }
            }

            if (setting.ResetBundleName)
            {
                ClearAssetBundleNames(setting.IsShowProgressBar);
                SetAssetBundleNames(setting.IsShowProgressBar);
            }

            BundlePackConfig packConfig = Util.FileUtil.ReadFromBinary <BundlePackConfig>(BundlePackUtil.GetPackConfigPath());

            assetBundleManifest = PackAssetBundle(packConfig);

            return(true);
        }
예제 #6
0
        /// <summary>
        /// 根据配置中的数据设置BundleName
        /// </summary>
        /// <param name="isShowProgressBar">是否显示进度</param>
        public static void SetAssetBundleNames(bool isShowProgressBar = false)
        {
            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());

            AssetImporter assetImporter = AssetImporter.GetAtPath(AssetAddressConfig.CONFIG_PATH);

            assetImporter.assetBundleName = AssetAddressConfig.CONFIG_ASSET_BUNDLE_NAME;

            AssetAddressData[] datas = (from groupData in tagConfig.GroupDatas
                                        from detailData in groupData.AssetDatas
                                        select detailData).ToArray();

            if (isShowProgressBar)
            {
                EditorUtility.DisplayProgressBar("Set Bundle Names", "", 0f);
            }

            if (datas != null && datas.Length > 0)
            {
                for (int i = 0; i < datas.Length; i++)
                {
                    if (isShowProgressBar)
                    {
                        EditorUtility.DisplayProgressBar("Set Bundle Names", datas[i].AssetPath, i / (float)datas.Length);
                    }
                    string        assetPath  = datas[i].AssetPath;
                    string        bundlePath = datas[i].BundlePath;
                    AssetImporter ai         = AssetImporter.GetAtPath(assetPath);
                    ai.assetBundleName = bundlePath;

                    if (Path.GetExtension(assetPath).ToLower() == ".spriteatlas")
                    {
                        SetSpriteBundleNameByAtlas(assetPath, bundlePath);
                    }
                }
            }
            if (isShowProgressBar)
            {
                EditorUtility.ClearProgressBar();
            }

            AssetDatabase.SaveAssets();
        }
예제 #7
0
        public static Dictionary <string, string> CollectionAssetPathToBundleNames()
        {
            Dictionary <string, string> pathToNames = new Dictionary <string, string>();

            pathToNames[AssetAddressConfig.CONFIG_PATH] = AssetAddressConfig.CONFIG_ASSET_BUNDLE_NAME.ToLower();

            #region Collection
            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());
            AssetAddressData[]   datas     = (from groupData in tagConfig.GroupDatas
                                              from detailData in groupData.AssetDatas
                                              select detailData).ToArray();

            long elapsedMS = Leyoutech.Utility.DebugUtility.GetMillisecondsSinceStartup();
            for (int iData = 0; iData < datas.Length; iData++)
            {
                AssetAddressData iterData   = datas[iData];
                string           assetPath  = iterData.AssetPath;
                string           bundleName = iterData.BundlePath.ToLower();
                pathToNames[assetPath] = bundleName;

                if (Path.GetExtension(assetPath).ToLower() != ".spriteatlas")
                {
                    continue;
                }

                SpriteAtlas atlas = AssetDatabase.LoadAssetAtPath <SpriteAtlas>(assetPath);
                if (atlas == null)
                {
                    continue;
                }

                UnityObject[] packables = atlas.GetPackables();
                for (int iPackable = 0; iPackable < packables.Length; iPackable++)
                {
                    UnityObject iterPackable = packables[iPackable];
                    if (iterPackable.GetType() == typeof(Sprite))
                    {
                        pathToNames[AssetDatabase.GetAssetPath(iterPackable)] = bundleName;
                    }
                    else if (iterPackable.GetType() == typeof(DefaultAsset))
                    {
                        string   folderPath = AssetDatabase.GetAssetPath(iterPackable);
                        string[] assets     = AssetDatabaseUtil.FindAssetInFolder <Sprite>(folderPath);
                        for (int iAsset = 0; iAsset < assets.Length; iAsset++)
                        {
                            pathToNames[assets[iAsset]] = bundleName;
                        }
                    }
                }
            }
            elapsedMS = Leyoutech.Utility.DebugUtility.GetMillisecondsSinceStartup() - elapsedMS;
            Leyoutech.Utility.DebugUtility.Log(Leyoutech.BuildPipeline.BuildPipelineGraph.LOG_TAG, $"Collection all bundleName count ({pathToNames.Count}) elapsed {Leyoutech.Utility.DebugUtility.FormatMilliseconds(elapsedMS)}");
            #endregion
            return(pathToNames);
        }
예제 #8
0
        /// <summary>
        /// 生成Class,用于标识Address
        /// </summary>
        public static void CreateAddressKeyClass()
        {
            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());

            List <string> fieldNameAndValues = new List <string>();

            foreach (var group in tagConfig.GroupDatas)
            {
                if (!group.IsMain || !group.IsGenAddress)
                {
                    continue;
                }
                string prefix = group.GroupName.Replace(" ", "");

                foreach (var data in group.AssetDatas)
                {
                    string address = data.AssetAddress;

                    string tempName = address;
                    if (tempName.IndexOf('/') > 0)
                    {
                        tempName = Path.GetFileNameWithoutExtension(tempName);
                    }
                    tempName = tempName.Replace(" ", "_").Replace(".", "_").Replace("-", "_");

                    string fieldName = (prefix + "_" + tempName).ToUpper();
                    string content   = $"{fieldName} = @\"{address}\";";

                    if (fieldNameAndValues.IndexOf(content) < 0)
                    {
                        fieldNameAndValues.Add(content);
                    }
                }
            }

            StringBuilder classSB = new StringBuilder();

            classSB.AppendLine("namespace Leyoutech.Core.Loader.Config");
            classSB.AppendLine("{");
            classSB.AppendLine("\tpublic static class AssetAddressKey");
            classSB.AppendLine("\t{");

            fieldNameAndValues.ForEach((value) =>
            {
                classSB.AppendLine("\t\tpublic const string " + value);
            });

            classSB.AppendLine("\t}");
            classSB.AppendLine("}");

            string filePath = Application.dataPath + "/Scripts/Core/Loader/Config/AssetAddressKey.cs";

            File.WriteAllText(filePath, classSB.ToString());
        }
예제 #9
0
        /// <summary>
        /// 通过资源的分组信息,生成地址的配置文件
        /// </summary>
        public static void UpdateAddressConfig()
        {
            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());
            AssetAddressConfig   config    = AssetDatabase.LoadAssetAtPath <AssetAddressConfig>(AssetAddressConfig.CONFIG_PATH);

            if (config == null)
            {
                config = ScriptableObject.CreateInstance <AssetAddressConfig>();
                AssetDatabase.CreateAsset(config, AssetAddressConfig.CONFIG_PATH);
                AssetDatabase.ImportAsset(AssetAddressConfig.CONFIG_PATH);
            }

            AssetAddressData[] datas = (from groupData in tagConfig.GroupDatas
                                        where groupData.IsMain == true
                                        from assetData in groupData.AssetDatas
                                        select assetData).ToArray();

            List <AssetAddressData> addressDatas = new List <AssetAddressData>();

            foreach (var assetData in datas)
            {
                AssetAddressData addressData = new Leyoutech.Core.Loader.Config.AssetAddressData()
                {
                    AssetAddress = assetData.AssetAddress,
                    AssetPath    = assetData.AssetPath,
                    BundlePath   = assetData.BundlePath,
                };
                if (assetData.Labels != null && assetData.Labels.Length > 0)
                {
                    addressData.Labels = new string[assetData.Labels.Length];
                    Array.Copy(assetData.Labels, addressData.Labels, addressData.Labels.Length);
                }
                addressDatas.Add(addressData);
            }

            config.AddressDatas = addressDatas.ToArray();
            EditorUtility.SetDirty(config);

            AssetDatabase.SaveAssets();
        }
예제 #10
0
        /// <summary>
        /// 移动文件
        /// </summary>
        void MoveFile(string bundlname)
        {
            BundlePackConfig m_PackConfig    = Util.FileUtil.ReadFromBinary <BundlePackConfig>(BundlePackUtil.GetPackConfigPath());
            string           outputTargetDir = m_PackConfig.OutputDirPath + "/" + m_PackConfig.GetBuildTarget().ToString() + "/" + AssetBundleConst.ASSETBUNDLE_MAINFEST_NAME + "_temp";

            //bund 文件
            string path  = string.Format("{0}/{1}", outPath_temp, bundlname);
            string path1 = string.Format("{0}/{1}", outPath_true, bundlname);

            if (File.Exists(path))
            {
                File.Delete(path1);
                File.Move(path, path1);
            }

            //bund manifest文件
            string path2 = string.Format("{0}/{1}.{2}", outPath_temp, bundlname, "manifest");
            string path3 = string.Format("{0}/{1}.{2}", outPath_true, bundlname, "manifest");

            if (File.Exists(path2))
            {
                File.Delete(path3);
                File.Move(path2, path3);
            }
        }
예제 #11
0
        /// <summary>
        /// 获得正在的输出路径
        /// </summary>
        /// <returns></returns>
        string GetTrueOutPath()
        {
            BundlePackConfig m_PackConfig = Util.FileUtil.ReadFromBinary <BundlePackConfig>(BundlePackUtil.GetPackConfigPath());

            options     = m_PackConfig.GetBundleOptions();
            buildTarget = m_PackConfig.GetBuildTarget();

            string outputTargetDir = m_PackConfig.OutputDirPath + "/" + buildTarget.ToString() + "/" + AssetBundleConst.ASSETBUNDLE_MAINFEST_NAME;

            if (!Directory.Exists(outputTargetDir))
            {
                Debug.LogError("eternity_assetbunles/StandaloneWindows64/assetbundles  -------> AB 存放路径不存在");
                return(string.Empty);
            }
            return(outputTargetDir);
        }
예제 #12
0
        private void ToInit()
        {
            string      AssetRootDir = UnityEditor.EditorPrefs.GetString("BT_ASSET_BUNDLE_PATH_PREFS", string.Empty) + "/" + EditorUserBuildSettings.activeBuildTarget + "/assetbundles";
            string      manifestPath = $"{AssetRootDir}/{AssetBundleConst.ASSETBUNDLE_MAINFEST_NAME}";
            AssetBundle manifestAB   = AssetBundle.LoadFromFile(manifestPath);

            m_AssetBundleManifest = manifestAB.LoadAsset <AssetBundleManifest>("AssetBundleManifest");
            // AB释放掉
            manifestAB.Unload(false);

            AssetBundleTagConfig tagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());

            Alldatas = (from groupData in tagConfig.GroupDatas
                        from assetData in groupData.AssetDatas
                        select assetData).ToArray();

            bInit = true;
        }
예제 #13
0
 private void OnEnable()
 {
     m_TagConfig     = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());
     m_PackConfigGUI = new BundlePackConfigGUI();
 }
예제 #14
0
        private void DrawOperation()
        {
            if (GUILayout.Button("Update Asset Group"))
            {
                BundlePackUtil.UpdateTagConfig();

                m_TagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());
                FilterTreeModel();
            }
            if (GUILayout.Button("Update Address Config"))
            {
                BundlePackUtil.UpdateAddressConfig();
            }
            if (GUILayout.Button("Create Key Class"))
            {
                BundlePackUtil.CreateAddressKeyClass();
            }
            if (GUILayout.Button("Clear Asset Bundle Names"))
            {
                BundlePackUtil.ClearAssetBundleNames(true);
            }
            if (GUILayout.Button("Set Asset Bundle Names"))
            {
                BundlePackUtil.SetAssetBundleNames(true);
            }

            GUILayout.FlexibleSpace();

            EditorGUIUtil.BeginGUIBackgroundColor(Color.red);
            {
                if (GUILayout.Button("Pack Without Depends", GUILayout.Height(30)))
                {
                    EditorApplication.delayCall += () =>
                    {
                        BundlePackUtil.PackBundleSetting packBundleSetting = new BundlePackUtil.PackBundleSetting();
                        packBundleSetting.FindDepend        = false;
                        packBundleSetting.IsShowProgressBar = true;
                        packBundleSetting.ResetBundleName   = true;
                        packBundleSetting.UpdateConfigs     = true;
                        if (BundlePackUtil.PackBundle(out AssetBundleManifest assetBundleManifest, packBundleSetting))
                        {
                            EditorUtility.DisplayDialog("Success", "Pack AssetBundle Success", "OK");
                        }
                    };
                }
                if (GUILayout.Button("Pack With Depends", GUILayout.Height(30)))
                {
                    EditorApplication.delayCall += () =>
                    {
                        BundlePackUtil.PackBundleSetting packBundleSetting = new BundlePackUtil.PackBundleSetting();
                        packBundleSetting.FindDepend        = true;
                        packBundleSetting.IsShowProgressBar = true;
                        packBundleSetting.ResetBundleName   = true;
                        packBundleSetting.UpdateConfigs     = true;
                        if (BundlePackUtil.PackBundle(out AssetBundleManifest assetBundleManifest, packBundleSetting))
                        {
                            EditorUtility.DisplayDialog("Success", "Pack AssetBundle Success", "OK");
                        }
                    };
                }
            }
            EditorGUIUtil.EndGUIBackgroundColor();
        }
    }
}
예제 #15
0
        private void DrawToolbar()
        {
            EditorGUILayout.BeginHorizontal("toolbar", GUILayout.ExpandWidth(true));
            {
                if (GUILayout.Button(m_IsExpandAll? "\u25BC" : "\u25BA", "toolbarbutton", GUILayout.Width(60)))//展开或折叠TreeView的项
                {
                    m_IsExpandAll = !m_IsExpandAll;
                    if (m_IsExpandAll)
                    {
                        m_DetailGroupTreeView.ExpandAll();
                    }
                    else
                    {
                        m_DetailGroupTreeView.CollapseAll();
                    }
                }
                EditorGUILayout.Space();

                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Find Auto Group", "toolbarbutton", GUILayout.Width(120)))//开始查找依赖资源
                {
                    BundlePackUtil.FindAndAddAutoGroup(true);

                    m_TagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());
                    FilterTreeModel();
                }

                if (GUILayout.Button("Remove Auto Group", "toolbarbutton", GUILayout.Width(120)))//删除依赖资源分组
                {
                    BundlePackUtil.DeleteAutoGroup();
                    m_TagConfig = Util.FileUtil.ReadFromBinary <AssetBundleTagConfig>(BundlePackUtil.GetTagConfigPath());
                    FilterTreeModel();
                }

                if (GUILayout.Button("Open Depend Win", "toolbarbutton", GUILayout.Width(160)))//打开依赖详细窗口
                {
                    AssetDependWindow.ShowWin();
                }

                int newSelectedIndex = EditorGUILayout.Popup(m_SelecteddSearchParamIndex, m_SearchParams, "ToolbarDropDown", GUILayout.Width(80));
                if (newSelectedIndex != m_SelecteddSearchParamIndex)
                {
                    m_SelecteddSearchParamIndex = newSelectedIndex;
                    FilterTreeModel();
                }

                EditorGUILayout.LabelField("", GUILayout.Width(200));
                Rect   lastRect         = GUILayoutUtility.GetLastRect();
                Rect   searchFieldRect  = new Rect(lastRect.x, lastRect.y, 180, 16);
                string newSearchText    = EditorGUI.TextField(searchFieldRect, "", m_SearchText, "toolbarSeachTextField");;
                Rect   searchCancelRect = new Rect(searchFieldRect.x + searchFieldRect.width, searchFieldRect.y, 16, 16);
                if (GUI.Button(searchCancelRect, "", "ToolbarSeachCancelButton"))
                {
                    newSearchText = "";
                    GUI.FocusControl("");
                }
                if (newSearchText != m_SearchText)
                {
                    m_SearchText = newSearchText;
                    FilterTreeModel();

                    m_IsExpandAll = true;
                    m_DetailGroupTreeView.ExpandAll();
                }
            }
            EditorGUILayout.EndHorizontal();
        }
예제 #16
0
        internal void LayoutGUI()
        {
            var centeredStyle = new GUIStyle(GUI.skin.GetStyle("Label"));

            centeredStyle.alignment = TextAnchor.UpperCenter;
            GUILayout.Label(new GUIContent("Bundle Pack Config"), centeredStyle);

            EditorGUILayout.Space();

            EditorGUILayout.BeginVertical();
            {
                m_PackConfig.OutputDirPath = EditorGUILayoutUtil.DrawDiskFolderSelection("Bundle Output", m_PackConfig.OutputDirPath);
                if (string.IsNullOrEmpty(m_PackConfig.OutputDirPath))
                {
                    m_PackConfig.OutputDirPath = GetDefaultOutputDir();
                }
                m_PackConfig.BuildTarget = (ValidBuildTarget)EditorGUILayout.EnumPopup(m_TargetContent, m_PackConfig.BuildTarget);

                m_AdvancedSettings = EditorGUILayout.Foldout(m_AdvancedSettings, "Advanced Settings");
                if (m_AdvancedSettings)
                {
                    EditorGUIUtil.BeginIndent();
                    {
                        m_PackConfig.CleanupBeforeBuild = EditorGUILayout.Toggle(m_CleanBeforeBuildContent, m_PackConfig.CleanupBeforeBuild);
                        m_PackConfig.Compression        = (CompressOptions)EditorGUILayout.IntPopup(m_CompressionContent, (int)m_PackConfig.Compression, m_CompressionContents, m_CompressionValues);

                        EditorGUILayout.Space();

                        EditorGUI.BeginChangeCheck();
                        {
                            m_IsForceRebuild = EditorGUILayout.Toggle(m_ForceRebuildContent, m_IsForceRebuild);
                            m_IsAppendHash   = EditorGUILayout.Toggle(m_AppendHashContent, m_IsAppendHash);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            if (m_IsForceRebuild)
                            {
                                m_PackConfig.BundleOptions |= BuildAssetBundleOptions.ForceRebuildAssetBundle;
                            }
                            else
                            {
                                m_PackConfig.BundleOptions &= ~BuildAssetBundleOptions.ForceRebuildAssetBundle;
                            }
                            if (m_IsAppendHash)
                            {
                                m_PackConfig.BundleOptions |= BuildAssetBundleOptions.AppendHashToAssetBundleName;
                            }
                            else
                            {
                                m_PackConfig.BundleOptions &= ~BuildAssetBundleOptions.AppendHashToAssetBundleName;
                            }
                        }
                    }
                    EditorGUIUtil.EndIndent();
                }

                EditorGUILayout.Space();
                if (GUILayout.Button("Pack Bundle"))
                {
                    EditorApplication.delayCall += () =>
                    {
                        BundlePackUtil.PackAssetBundle(m_PackConfig);
                    };
                }
            }
            EditorGUILayout.EndVertical();


            if (GUI.changed)
            {
                Util.FileUtil.SaveToBinary <BundlePackConfig>(BundlePackUtil.GetPackConfigPath(), m_PackConfig);
            }
        }