//************************************ // 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); }
/// <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; }