Beispiel #1
0
        /// <summary>
        /// 加载AB配置表
        /// </summary>
        /// <returns></returns>
        public bool LoadAssetBundleConfig(bool isInit = true)
        {
            AssetBundleConfig abConfig = null;

#if UNITY_EDITOR
            if (ResourceManager.Instance.m_LoadFromAssetBundle)
            {
#endif
            //初始化时候的ab配置文件在streamingAssets文件夹中
            string configPath = Application.streamingAssetsPath + "/" + m_ABConfigABName;
            //非初始化,检查热更后进来的
            if (!isInit)
            {
                //热更完毕后检查配置文件是否热更了
                string hotABPath = HotPatchManager.Instance.ComputeABPath(m_ABConfigABName);
                if (string.IsNullOrEmpty(hotABPath))
                {
                    return(true);
                }
                else
                {
                    //文件改变了,卸载本地的ab包,从热更路径下下载新的ab包
                    if (configAB != null)
                    {
                        configAB.Unload(true);
                        configPath = hotABPath;
                    }
                }
            }

            m_AssetBundleInfoDic.Clear();

            //加密后的ab包要先解密,才能加载
            if (Encrypt)
            {
                byte[] bytes = AES.AESFileByteDecrypt(configPath, FrameConstr.m_ABSecretKey);

                configAB = AssetBundle.LoadFromMemory(bytes);
            }
            else
            {
                configAB = AssetBundle.LoadFromFile(configPath);
            }

            TextAsset textAsset = configAB.LoadAsset <TextAsset>(m_ABConfigABName);
            if (textAsset == null)
            {
                Debug.LogError("AssetBundleConfig is no exist!");
                return(false);
            }
            //创建一个内存流
            MemoryStream stream = new MemoryStream(textAsset.bytes);
            //二进制序列化对象
            BinaryFormatter bf = new BinaryFormatter();
            abConfig = (AssetBundleConfig)bf.Deserialize(stream);
            //关闭内存流
            stream.Close();
#if UNITY_EDITOR
        }

        else
        {
            m_AssetBundleInfoDic.Clear();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(Application.dataPath + "/AssetBundleConfig.xml");
            XmlSerializer xs = new XmlSerializer(typeof(AssetBundleConfig));
            StringReader  sr = new StringReader(xmlDoc.InnerXml);
            abConfig = (AssetBundleConfig)xs.Deserialize(sr);
        }
#endif
            for (int i = 0; i < abConfig.ABList.Count; ++i)
            {
                ABBase abBase = abConfig.ABList[i];

                AssetBundleInfo abInfo = new AssetBundleInfo();
                abInfo.m_Crc                 = abBase.Crc;
                abInfo.m_AssetName           = abBase.AssetName;
                abInfo.m_ABName              = abBase.ABName;
                abInfo.m_DependceAssetBundle = abBase.ABDependce;

                if (m_AssetBundleInfoDic.ContainsKey(abInfo.m_Crc))
                {
                    Debug.LogError("重复的Crc : 资源名:" + abInfo.m_AssetName + " ab包名:" + abInfo.m_ABName);
                }
                else
                {
                    m_AssetBundleInfoDic.Add(abInfo.m_Crc, abInfo);
                }
            }

            return(true);
        }
        /// <summary>
        /// 写入配置文件
        /// </summary>
        static void WriteData()
        {
            //记录所有即将打包的资源文件路径和它的包名,用来生成配置文件用的
            //key是资源文件路径,value是资源文件包名,属于哪一个ab包
            Dictionary <string, string> resPathDic = new Dictionary <string, string>();

            //获取所有的被标记为要打AB包的资源文件
            string[] allBundles = AssetDatabase.GetAllAssetBundleNames();
            for (int i = 0; i < allBundles.Length; ++i)
            {
                //根据assetBundle的名字获取assetBundle的全路径
                string[] allBundlePath = AssetDatabase.GetAssetPathsFromAssetBundle(allBundles[i]);
                for (int j = 0; j < allBundlePath.Length; j++)
                {
                    //过滤assetBundle文件中的脚本文件
                    if (allBundlePath[j].EndsWith(".cs"))
                    {
                        continue;
                    }
                    resPathDic.Add(allBundlePath[j], allBundles[i]);
                    Debug.Log("此AB包:" + allBundles[i] + "==下面包含的资源文件路径" + allBundlePath[j]);
                }
            }


            //创建一个AB配置文件
            AssetBundleConfig config = new AssetBundleConfig();

            //记录AB文件列表
            config.ABList = new List <ABBase>();

            //遍历所有的资源文件字典,
            foreach (var path in resPathDic.Keys)
            {
                //判断是否是有效路径
                if (!ValidPath(path))
                {
                    continue;
                }
                ABBase abBase = new ABBase();
                abBase.Path      = path;
                abBase.Crc       = Crc32.GetCrc32(path);                      //Crc加密
                abBase.ABName    = resPathDic[path];                          //ab包名
                abBase.AssetName = path.Remove(0, path.LastIndexOf("/") + 1); //截掉最后一个/,得到资源文件名称
                Debug.Log("abBase.AssetName" + abBase.AssetName);
                abBase.ABDependce = new List <string>();
                //获取这个资源文件的所有依赖项
                string[] resDependce = AssetDatabase.GetDependencies(path);
                for (int i = 0; i < resDependce.Length; i++)
                {
                    string resDependcePath = resDependce[i];    //依赖资源的路径
                                                                //去掉这个资源文件自己和cs文件
                    if (resDependcePath == path || path.EndsWith(".cs"))
                    {
                        continue;
                    }

                    string abName = string.Empty;
                    //通过依赖资源的路径获取这个依赖资源的包名
                    if (resPathDic.TryGetValue(resDependcePath, out abName))
                    {
                        //依赖资源的包名和自己本身资源在同一个包不管
                        if (abName == resPathDic[path])
                        {
                            continue;
                        }
                        //将这个包名添加到这个资源的依赖列表中,
                        //可能这个资源的多个依赖资源在同一个包中
                        //所以只添加一次就够了
                        if (!abBase.ABDependce.Contains(abName))
                        {
                            abBase.ABDependce.Add(abName);
                        }
                    }
                }
                config.ABList.Add(abBase);
            }

            //写入xml
            string xmlPath = Application.dataPath + "/AssetBundleConfig.xml";

            if (File.Exists(xmlPath))
            {
                File.Delete(xmlPath);
            }

            using (FileStream fileStream = new FileStream(xmlPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                using (StreamWriter sw = new StreamWriter(fileStream, System.Text.Encoding.UTF8))
                {
                    XmlSerializer xs = new XmlSerializer(config.GetType());
                    xs.Serialize(sw, config);
                }
            }

            //写入二进制
            foreach (ABBase abBase in config.ABList)
            {
                abBase.Path = "";
            }

            //提前在ABBYTEPATH这个路径下创建一个2进制文件,将前面收集到的要打包的文件信息写入这个2进制文件
            //创建一个文件流对象
            using (FileStream fs = new FileStream(ABBYTEPATH, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                fs.Seek(0, SeekOrigin.Begin);
                fs.SetLength(0);

                //二进制序列化对象
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, config);
                fs.Close();
            }

            //刷新
            AssetDatabase.Refresh();

            //设置这个2进制文件也打包
            SetABName("assetbundleconfig", ABBYTEPATH);
        }