Example #1
0
        //************************************
        // Method:   try load a general asset (any type inherited from UnityEngine.Object)
        //Notice :    this will quickly load an asset if it already in cache, but it may fail
        //************************************
        public bool try_load_asset_immediately(string _asset_path, Type _type, AssetResource _result, bool _lock_asset = true)
        {
            if (is_destroyed_)
            {
                return(false);
            }
            if (_result.get_obj() != null)
            {
                Debug.LogError("resused an old assetresoure! you should create a new!");
                return(false);
            }
            if (!bundleobj_cache_.is_first_resource_loaded())
            {
                return(false);
            }

            if (_lock_asset)
            {
                if (asset_lock_.is_locked(_asset_path))
                {
                    return(false);
                }
            }

            AssetObject found_obj = assetobj_cache_.get_from_cache(_asset_path);

            if (found_obj != null)
            {
                _result.set_obj(found_obj);
            }
            else
            {
                return(false);
            }

            return(true);
        }
Example #2
0
        /// <summary>
        /// <para>加载UnityEngine.Object资源,资源不再使用后要调用AssetResource.Destroy()来销毁</para>
        /// <para>_asset_path:资源路径,eg: "Assets/Res/DefaultRes.prefab"</para>
        /// <para>_type:加载资源的类型</para>
        /// <para>_result:协程结束后返回加载资源的结果</para>
        /// <para>_lock_asset:为避免其他协程加载资源,是否进行锁定操作</para>
        /// <para>_scene_asset:是否是场景资源</para>
        /// <para>_scene_name:场景资源的名字</para>
        /// </summary>
        public IEnumerator load_asset(string _asset_path, Type _type, AssetResource _result, bool _lock_asset = true, bool _scene_asset = false, string _scene_name = "")
        {
            if (is_destroyed_)
            {
                yield break;
            }

            bool is_ui_asset = _asset_path.Contains("Assets/Res/UI");

            if (Const.Language != LanguageType.SIMPLE_CHINESE)
            {
                LocalizeManager.Instance.LocalizePath(ref _asset_path);
            }

#if UNITY_EDITOR
            // 在编辑器下检查资源是否添加到打包配置中(因为lightmap的bug,.unity3d场景暂时不进行资源检查)
            if (!CheckAssetCfged(_asset_path))
            {
                Debug.LogError(string.Format("asset {0} is not configured for bundle, load failed!", _asset_path));
                yield break;
            }
#endif

            if (_result.get_obj() != null)
            {
                Debug.LogError("resused an old assetresoure! you should create a new!");
                yield break;
            }
            //1. 等待first res加载完毕,其中包含bundleinfo
            while (!bundleobj_cache_.is_first_resource_loaded())
            {
                yield return(new WaitForEndOfFrame());
            }
            loading_ = true;

            // 检查资源对应的分包是否已经下载完毕
            int patch_id;
            if (!xpatch.XPatchManager.Instance.IsAssetDownloaded(_asset_path, out patch_id))
            {
                Debug.Log(string.Format("asset {0} is not download for bundle!", _asset_path));
                yield break;
            }

            //2. 锁定资源,避免加载同一份asset
            IEnumerator ielock = null;
            if (_lock_asset)
            {
                if (!asset_lock_.try_lock(_asset_path))
                {
                    ielock = asset_lock_.try_lock_croutine(_asset_path);
                    coroutine_locked_assets_.Add(ielock, _asset_path);
                    yield return(StartCoroutine(ielock));
                }
            }

            //3. 检查Cache中是否已经有对应的bundle,否则需要进行加载
            AssetObject found_obj = assetobj_cache_.get_from_cache(_asset_path);
            if (found_obj != null)
            {
                _result.set_obj(found_obj);
                if (_scene_asset)
                {
                    //load level
                    sceneLoadAsyncOp = SceneManager.LoadSceneAsync(_scene_name);
                    yield return(sceneLoadAsyncOp);
                }
            }
            else
            {
#if UNITY_EDITOR
                if (!EnableBundleInEditor)
                {
                    //editor enviroment
                    yield return(StartCoroutine(load_asset_from_assetdatabase(_asset_path, _type, _result, _lock_asset, _scene_asset, _scene_name)));
                }
                else
#endif
                {
                    //bundle enviroment
                    //4.从bundleinfo中获取asset的依赖项
                    AssetBundleInfoItem bundle_info = bundleobj_cache_.get_asset_bundle_info(_asset_path);
                    if (bundle_info == null)
                    {
                        Debug.LogError("Dynamic bundle not find!Editor path is " + _asset_path);
                        goto EXIT_LOAD_ASSET;
                    }
                    UnityEngine.Object  loaded_asset = null;
                    List <BundleObject> all_bundles  = new List <BundleObject>();

                    List <List <string> > sort_depends_list = bundleobj_cache_.get_asset_all_dependence(_asset_path);
                    foreach (List <string> sub_list in sort_depends_list)
                    {
                        // 先判断是否在Cache中
                        if (bundleobj_cache_.is_all_in_cache(sub_list))
                        {
                            foreach (string path in sub_list)
                            {
                                load_bundle_from_cache(path, all_bundles);
                            }
                        }
                        else
                        {
                            List <string> fail_list = new List <string>();
                            yield return(StartCoroutine(try_load_bundle_list_coroutine(sub_list, all_bundles, fail_list, is_ui_asset)));

                            //被其他协程锁定的bundle等待解锁后再进行加载
                            foreach (string depend_bundle_path in fail_list)
                            {
                                //lock
                                if (!bundle_lock_.try_lock(depend_bundle_path))
                                {
                                    yield return(StartCoroutine(bundle_lock_.try_lock_croutine(depend_bundle_path)));
                                }
                                //load bundle and add ref
                                if (!load_bundle_from_cache(depend_bundle_path, all_bundles))
                                {
                                    yield return(StartCoroutine(load_bundle_from_disk_coroutine(depend_bundle_path, all_bundles, is_ui_asset)));
                                }
                                //unlock
                                bundle_lock_.unlock(depend_bundle_path);
                            }
                        }
                    }

                    //5.锁定asset并进行加载
                    if (!bundle_lock_.try_lock(_asset_path))
                    {
                        yield return(StartCoroutine(bundle_lock_.try_lock_croutine(_asset_path)));
                    }
                    //load bundle and add ref
                    if (!load_bundle_from_cache(_asset_path, all_bundles))
                    {
                        yield return(StartCoroutine(load_bundle_from_disk_coroutine(_asset_path, all_bundles, is_ui_asset)));
                    }
                    //unlock
                    bundle_lock_.unlock(_asset_path);

                    if (all_bundles.Count < 1)
                    {
                        goto EXIT_LOAD_ASSET;
                    }

                    //6.从bundle中加载mainasset
                    // 在调用Bundle.Load()之前,需要将缓存所有的依赖bundle
                    if (!_scene_asset)
                    {
                        BundleObject root = all_bundles[all_bundles.Count - 1];
                        // 获取在bundle中的资源名字

                        /*string asset_name = root.get_asset_path_;
                         * int last_path_idx = asset_name.LastIndexOf('/');
                         * if(last_path_idx != -1)
                         *  asset_name = asset_name.Substring(last_path_idx + 1);
                         * last_path_idx = asset_name.LastIndexOf('.');
                         * if (last_path_idx != -1)
                         *  asset_name = asset_name.Substring(0, last_path_idx);*/

                        //loaded_asset = bundleobj_cache_.load_main_asset(root.get_asset_bundle_, _type, BundleNameDef.MAIN);
                        var loadReq = root.get_asset_bundle_.LoadAssetAsync(BundleNameDef.MAIN, _type);
                        yield return(loadReq);

                        loaded_asset = loadReq.asset;

                        if (loaded_asset == null)
                        {
                            Debug.LogError(string.Format("asset counld not be loaded {0} ,check xls or your project", _asset_path));
                            // 加载失败后要将依赖的bundle的引用计数减少
                            foreach (BundleObject bo in all_bundles)
                            {
                                bo.decrease_ref();// 因为load bundle的时候增加了引用计数,所以此处需要减少
                            }
                            goto EXIT_LOAD_ASSET;
                        }
                    }
                    // 场景资源在缓存bundle之后就可以使用
                    else
                    {
                        sceneLoadAsyncOp = SceneManager.LoadSceneAsync(_scene_name);
                        yield return(sceneLoadAsyncOp);
                    }

                    //7. 创建assetobject并添加到Cache中
                    AssetObject ao = _scene_asset ? new SceneAssetObject(_asset_path) : new AssetObject(_asset_path, loaded_asset);
                    foreach (BundleObject bo in all_bundles)
                    {
                        AssetBundleInfoItem bundle_item_depend = bundleobj_cache_.get_asset_bundle_info(bo.get_asset_path_);
                        bool shared = bundle_item_depend.shared;
                        // 当assetbundle不被多个资源引用时,可以立即将assetbundle的文件镜像卸载,并从Cache中清除
                        // Atlas经过特殊处理,虽然被多个资源引用,但是也会立即卸载

                        /// FIXME
                        /// 在2017版本中,此时unload assetbundle会报错

                        /*if(!shared)
                         * {
                         *  bo.destroy(false);
                         *  bundleobj_cache_.remove_bundle_object_from_cache(bo.get_asset_path_);
                         * }
                         * else*/
                        {
                            ao.add_depend_bundle(bo);
                        }
                        bo.decrease_ref();//decrease the ref added by load bundle
                    }
                    all_bundles.Clear();
                    assetobj_cache_.put_to_cache(_asset_path, ao);
                    _result.set_obj(ao);
                }
            }
            //9.unlock asset
EXIT_LOAD_ASSET:
            //unlock
            if (_lock_asset)
            {
                if (ielock != null)
                {
                    coroutine_locked_assets_.Remove(ielock);
                }
                asset_lock_.unlock(_asset_path);
            }

            loading_ = false;
        }