Esempio n. 1
0
        /// <summary>
        /// 异步资源加载,外部直接调用,(仅仅加载不需要实例化的资源,例如Texture和音频之类的)
        /// </summary>
        public void AsyncLoadResource(string path, OnAsyncFinish dealFinish, LoadResPriority priority, bool isSprite = false, uint crc = 0, params object[] paramList)
        {
            if (crc == 0)
            {
                crc = Crc32.GetCrc32(path);
            }

            AssetBundleInfo abInfo = GetCacheAssetBundleInfo(crc);

            if (abInfo != null)
            {
                dealFinish?.Invoke(path, abInfo.m_Obj, paramList);
                return;
            }

            //判断是否在加载中
            AsyncLoadResUnit unit = null;

            //没有找到这个异步加载单位,或者这个异步加载单位是空
            if (!m_LoadingAssetDic.TryGetValue(crc, out unit) || unit == null)
            {
                unit            = m_AsyncLoadResParamPool.Spawn(true);
                unit.m_Crc      = crc;
                unit.m_Path     = path;
                unit.m_Sprite   = isSprite;
                unit.m_Priority = priority;

                m_LoadingAssetDic.Add(crc, unit);            //添加到正在异步加载的资源dic中

                m_loadingAssetList[(int)priority].Add(unit); //按照加载优先级,添加到对应的正在异步加载的资源列表中
            }

            //往回调列表里面添加回调
            AsynCallBack callBack = m_AsynCallBackPool.Spawn(true);

            callBack.m_DealFinish = dealFinish;
            callBack.m_Params     = paramList;

            //往这个异步加载单位的回调列表中添加一个回调
            //可能多个地方加载同一份资源,这样做只加载一次资源,
            //加载完了后,根据回调列表一次返回这份资源
            unit.m_CallBackList.Add(callBack);
        }
Esempio n. 2
0
        /// <summary>
        /// 释放一个资源块
        /// </summary>
        /// <param name="abInfo"></param>
        public void ReleaseAssetBundle(AssetBundleInfo abInfo)
        {
            if (abInfo == null)
            {
                return;
            }

            //先卸载依赖资源
            if (abInfo.m_DependceAssetBundle != null && abInfo.m_DependceAssetBundle.Count > 0)
            {
                for (int i = 0; i < abInfo.m_DependceAssetBundle.Count; i++)
                {
                    UnloadAssetBundle(abInfo.m_DependceAssetBundle[i]);
                }
            }

            //再卸载这个资源
            UnloadAssetBundle(abInfo.m_ABName);
        }
Esempio n. 3
0
        /// <summary>
        /// 异步资源加载,针对ObjectManager的,(需要实例化对象的异步加载)
        /// </summary>
        public void AsyncLoadResource(string path, ResourceObj resObj, OnAsyncResObjFinish dealFinish, LoadResPriority priority, uint crc = 0, params object[] paramList)
        {
            AssetBundleInfo abInfo = GetCacheAssetBundleInfo(resObj.m_Crc);

            if (abInfo != null)
            {
                resObj.m_AssetBundleInfo = abInfo;
                if (dealFinish != null)
                {
                    dealFinish(path, resObj, paramList);
                }

                return;
            }
            //判断是否在加载中
            AsyncLoadResUnit unit = null;

            //没有找到这个异步加载单位,或者这个异步加载单位是空
            if (!m_LoadingAssetDic.TryGetValue(resObj.m_Crc, out unit) || unit == null)
            {
                unit            = m_AsyncLoadResParamPool.Spawn(true);
                unit.m_Crc      = resObj.m_Crc;
                unit.m_Path     = path;
                unit.m_Priority = priority;

                m_LoadingAssetDic.Add(resObj.m_Crc, unit);   //添加到正在异步加载的资源dic中

                m_loadingAssetList[(int)priority].Add(unit); //按照加载优先级,添加到对应的正在异步加载的资源列表中
            }

            //往回调列表里面添加回调
            AsynCallBack callBack = m_AsynCallBackPool.Spawn(true);

            callBack.m_Params = paramList;

            callBack.m_DealResObjFinish = dealFinish;
            callBack.m_ResObj           = resObj;
            //往这个异步加载单位的回调列表中添加一个回调
            //可能多个地方加载同一份资源,这样做只加载一次资源,
            //加载完了后,根据回调列表依次返回这份资源
            unit.m_CallBackList.Add(callBack);
        }
Esempio n. 4
0
        /// <summary>
        /// 回收一个资源
        /// </summary>
        /// <param name="abInfo"></param>
        /// <param name="destroy"></param>
        protected void DestoryResouceItem(AssetBundleInfo abInfo, bool destroyCache = false)
        {
            //资源是空的,或者正在被引用不能清除
            if (abInfo == null || abInfo.RefCount > 0)
            {
                return;
            }

            //设置的不清除缓存,就加入到双向链表里面
            if (!destroyCache)
            {
                m_NoRefrenceAssetMapList.InsetToHead(abInfo);
                return;
            }

            //AssetDic中删除这个资源
            if (!AssetDic.Remove(abInfo.m_Crc))
            {
                return;
            }

            //从双向链表中清除这个资源
            m_NoRefrenceAssetMapList.Remvoe(abInfo);

            //释放AssetBundle引用
            AssetBundleManager.Instance.ReleaseAssetBundle(abInfo);

            //清空资源对应的对象池
            ObjectManager.Instance.ClearPoolObject(abInfo.m_Crc);

            if (abInfo.m_Obj != null)
            {
#if UNITY_EDITOR
                Resources.UnloadUnusedAssets();
#endif
                abInfo.m_Obj = null;
                //编辑器下的卸载要用这个方法才能从内存卸载
            }
        }
Esempio n. 5
0
        /// <summary>
        /// 加载AssetBundle,存储到AssetBundleInfo.m_AssetBundle中,
        /// </summary>
        /// <param name="crc">AssetBundle的crc标记</param>
        /// <returns></returns>
        public AssetBundleInfo LoadAssetBundleInfo(uint crc)
        {
            AssetBundleInfo abInfo = null;

            if (!m_AssetBundleInfoDic.TryGetValue(crc, out abInfo) || abInfo == null)
            {
                Debug.LogError("bundle字典中没有找到item,或者找到了item是空,crc :" + crc);
                return(abInfo);
            }

            //加载该资源块中的资源
            abInfo.m_AssetBundle = LoadAssetBundle(abInfo.m_ABName);

            //加载该资源块中的资源所依赖的资源
            if (abInfo.m_DependceAssetBundle != null)
            {
                for (int i = 0; i < abInfo.m_DependceAssetBundle.Count; i++)
                {
                    LoadAssetBundle(abInfo.m_DependceAssetBundle[i]);
                }
            }

            return(abInfo);
        }
Esempio n. 6
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);
        }
Esempio n. 7
0
        /// <summary>
        /// 异步加载
        /// </summary>
        /// <returns></returns>
        IEnumerator AsyncLoadCor()
        {
            List <AsynCallBack> callBackList = null;

            while (true)
            {
                bool haveYield = false;     //是否已经等了一帧了
                                            //上次yield的时间
                long lastYiledTime = System.DateTime.Now.Ticks;

                //遍历优先级列表,从0开始,0表示最高
                for (int i = 0; i < (int)LoadResPriority.RES_NUM; i++)
                {
                    //每次循环,只要高级列表有东西,就一直加载高级列表资源,直到加载完毕
                    if (m_loadingAssetList[(int)LoadResPriority.RES_HIGHT].Count > 0)
                    {
                        i = (int)LoadResPriority.RES_HIGHT;
                    }
                    else if (m_loadingAssetList[(int)LoadResPriority.RES_MIDDLE].Count > 0)
                    {
                        i = (int)LoadResPriority.RES_MIDDLE;
                    }

                    List <AsyncLoadResUnit> loadingList = m_loadingAssetList[i];
                    if (loadingList.Count <= 0)
                    {
                        continue;
                    }

                    AsyncLoadResUnit loadintItem = loadingList[0];
                    loadingList.RemoveAt(0);
                    callBackList = loadintItem.m_CallBackList;

                    Object          obj    = null;
                    AssetBundleInfo abInfo = null;
#if UNITY_EDITOR
                    if (!m_LoadFromAssetBundle)
                    {
                        if (loadintItem.m_Sprite) //判断是否是Sprite,因为Unity Object不能转换成Sprite
                        {
                            obj = LoadAssetByEditor <Sprite>(loadintItem.m_Path);
                        }
                        else
                        {
                            obj = LoadAssetByEditor <Object>(loadintItem.m_Path);
                        }

                        //编辑器下模拟异步加载,等0.1f
                        yield return(new WaitForSeconds(0.1f));

                        abInfo = AssetBundleManager.Instance.FindAssetBundleInfo(loadintItem.m_Crc);

                        if (abInfo == null)
                        {
                            abInfo       = new AssetBundleInfo();
                            abInfo.m_Crc = loadintItem.m_Crc;
                        }
                    }
#endif
                    if (obj == null)
                    {
                        abInfo = AssetBundleManager.Instance.LoadAssetBundleInfoAsync(loadintItem.m_Crc);
                        yield return(abInfo);

                        if (abInfo.isDone)
                        {
                            if (abInfo != null && abInfo.m_AssetBundle != null)
                            {
                                AssetBundleRequest abRequest = null;
                                if (loadintItem.m_Sprite)   //判断是否是Sprite,因为Unity Object不能转换成Sprite
                                {
                                    abRequest = abInfo.m_AssetBundle.LoadAssetAsync <Sprite>(abInfo.m_AssetName);
                                }
                                else
                                {
                                    abRequest = abInfo.m_AssetBundle.LoadAssetAsync(abInfo.m_AssetName);
                                }
                                yield return(abRequest);

                                if (abRequest.isDone)
                                {
                                    obj = abRequest.asset;
                                }

                                lastYiledTime = System.DateTime.Now.Ticks;
                            }
                        }
                    }

                    CacheAssetBundleInfo(loadintItem.m_Path, ref abInfo, loadintItem.m_Crc, obj, callBackList.Count);

                    //处理回调
                    for (int j = 0; j < callBackList.Count; j++)
                    {
                        AsynCallBack callBack = callBackList[j];

                        //实例化对象的回调
                        if (callBack != null && callBack.m_DealResObjFinish != null && callBack.m_ResObj != null)
                        {
                            ResourceObj tempResObj = callBack.m_ResObj;

                            tempResObj.m_AssetBundleInfo = abInfo;

                            callBack.m_DealResObjFinish(loadintItem.m_Path, tempResObj, callBack.m_Params);

                            callBack.m_DealResObjFinish = null;

                            tempResObj = null;
                        }

                        //非实例化对象的回调
                        if (callBack != null && callBack.m_DealFinish != null)
                        {
                            callBack.m_DealFinish(loadintItem.m_Path, obj, callBack.m_Params);
                            callBack.m_DealFinish = null;
                        }


                        callBack.Reset();       //还原回调,并且回收
                        m_AsynCallBackPool.Recycle(callBack);
                    }

                    obj = null;
                    callBackList.Clear();
                    m_LoadingAssetDic.Remove(loadintItem.m_Crc);
                    loadintItem.Reset();
                    m_AsyncLoadResParamPool.Recycle(loadintItem);

                    //加载一个资源时间过长,等一帧
                    if (System.DateTime.Now.Ticks - lastYiledTime > MAXLOADRESTIME)
                    {
                        yield return(null);

                        lastYiledTime = System.DateTime.Now.Ticks;
                        haveYield     = true;
                    }
                }

                //内存循环加载很快,没有等一帧,但是加载整个优先级列表时间过长,等一帧
                if (!haveYield || System.DateTime.Now.Ticks - lastYiledTime > MAXLOADRESTIME)
                {
                    lastYiledTime = System.DateTime.Now.Ticks;
                    yield return(null);
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// 同步加载资源,针对给ObjectManager的接口
        /// 给ResourceObj.m_AssetBundleInfo赋值用的
        /// </summary>
        /// <param name="path"></param>
        /// <param name="resObj">传入的resourceObj,</param>
        /// <returns></returns>
        public ResourceObj LoadResource(string path, ResourceObj resObj)
        {
            if (resObj == null)
            {
                return(null);
            }

            //获取crc
            uint crc = resObj.m_Crc == 0 ? Crc32.GetCrc32(path) : resObj.m_Crc;

            //根据crc从缓存中获取 AssetBundle资源块信息
            AssetBundleInfo abInfo = GetCacheAssetBundleInfo(crc);

            if (abInfo != null)
            {
                resObj.m_AssetBundleInfo = abInfo;
                return(resObj);
            }

            Object obj = null;

#if UNITY_EDITOR
            if (!m_LoadFromAssetBundle)
            {
                abInfo = AssetBundleManager.Instance.FindAssetBundleInfo(crc);
                if (abInfo != null && abInfo.m_Obj != null)
                {
                    obj = abInfo.m_Obj;
                }
                else
                {
                    if (abInfo == null)
                    {
                        abInfo       = new AssetBundleInfo();
                        abInfo.m_Crc = crc;
                    }

                    obj = LoadAssetByEditor <Object>(path);
                }
            }
#endif
            //缓存中没有AssetBundle资源块信息,加载它
            if (obj == null)
            {
                abInfo = AssetBundleManager.Instance.LoadAssetBundleInfo(crc);

                if (abInfo != null && abInfo.m_AssetBundle != null)
                {
                    if (abInfo.m_Obj != null)
                    {
                        obj = abInfo.m_Obj;
                    }
                    else
                    {
                        obj = abInfo.m_AssetBundle.LoadAsset <Object>(abInfo.m_AssetName);
                    }
                }
            }

            //将加载的资源放入缓存中
            CacheAssetBundleInfo(path, ref abInfo, crc, obj);

            resObj.m_AssetBundleInfo = abInfo;

            abInfo.m_Clear = resObj.m_bClear;

            return(resObj);
        }
Esempio n. 9
0
        /// <summary>
        /// 预加载资源,仅仅加载不实例化
        /// </summary>
        /// <param name="path">资源路径</param>
        public void PreloadRes(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            uint crc = Crc32.GetCrc32(path);
            //根据crc从缓存中获取一个AssetBundleInfo
            AssetBundleInfo abInfo = GetCacheAssetBundleInfo(crc, 0);

            if (abInfo != null)
            {
                return;
            }

            Object obj = null;

#if UNITY_EDITOR
            if (!m_LoadFromAssetBundle)
            {
                abInfo = AssetBundleManager.Instance.FindAssetBundleInfo(crc);
                if (abInfo.m_Obj != null)
                {
                    obj = abInfo.m_Obj as Object;
                }
                else
                {
                    if (abInfo == null)
                    {
                        abInfo       = new AssetBundleInfo();
                        abInfo.m_Crc = crc;
                    }
                    obj = LoadAssetByEditor <Object>(path);
                }
            }
#endif
            if (obj == null)
            {
                abInfo = AssetBundleManager.Instance.LoadAssetBundleInfo(crc);
                if (abInfo != null && abInfo.m_AssetBundle != null)
                {
                    if (abInfo.m_Obj != null)
                    {
                        obj = abInfo.m_Obj as Object;
                    }
                    else
                    {
                        obj = abInfo.m_AssetBundle.LoadAsset <Object>(abInfo.m_AssetName);
                    }
                }
            }

            //缓存AssetBundle资源块
            CacheAssetBundleInfo(path, ref abInfo, crc, obj);

            //设置跳场景不清空缓存
            abInfo.m_Clear = false;

            //卸载资源设置成不销毁
            ReleaseResource(path, false);

            //上面的步骤就是提前加载一次资源,然后缓存AssetBundle资源块,
            //再将资源块设置成跳场景不清空缓存,预加载资源后应该就是跳场景进入游戏了
            //最后释放掉资源设置成不销毁,存到双向链表里面
        }