Beispiel #1
0
		private static void LoadOrResolveResourceInternal(Boolean bAsync, String path, Boolean syncIO, Boolean createImmediate, ResolveLevel resolveLevel, Action<UnityObject> onLoadFinish, Int32 dependLevel, String parentPath)
		{
			if (path == null)
				throw new ArgumentNullException("AsyncLoadOrResolveResource, path is null");

			//Debug.Log("AsyncLoadOrResolveResource: " + resolveLevel + ": " + path);

			AssetCache cache;
			if (!Instance.m_assetCacheMap.TryGetValue(path, out cache))		//缓存中无任何记录
			{
				cache = new AssetCache { path = path, asset = new WeakReference(null), bLoading = false, onLoadFinish = null, dependedLoadingCount = 0 };
				Instance.m_assetCacheMap.Add(path, cache);
			}
			Instance.IncDependedLoadingCount(cache);

			if (cache.bLoading)		//在加载中
			{
				++cache.concurrentLoadingCount;
				//等前一次加载完成
				cache.onLoadFinish += (asset) =>
				{
					onLoadFinish(asset);
				};
				return;
			}

			{
				UnityObject asset = cache.Asset;
				if (asset != null)		//已有资源缓存
				{
					if (resolveLevel <= ResolveLevel.None)		//只有ResolveLevel.None,才能直接返回此值,否则它的依赖还未 Resolve
					{
						if (!(asset is Material) || MakeSureIsMaterialAndHasAllTexture(cache))
						{
							Instance.IncChildrenDependedLoadingCount(cache);	//从Cache取出
							ProtectedOnLoadFinish(path, onLoadFinish, asset);
							return;
						}
					}

					if (cache.AssetBundle != null && (MakeSureIsMaterialAndHasAllTexture(cache) || Instance.m_donotReleaseOrResolveDepResPathSet.Contains(path)))
					{
						Instance.IncChildrenDependedLoadingCount(cache);	//从Cache取出
						ProtectedOnLoadFinish(path, onLoadFinish, asset);
						return;
					}
				}
			}

			//if (m_bEnableLog && dependLevel == 0)
			//    Log("no cache: " + path);
			//if (syncIO && createImmediate)
			//    Debug.LogWarning(String.Format("Really load bundle {0}, {1}, {2} #{3}", path, syncIO, createImmediate, dependLevel));

			//开始加载
			cache.bLoading = true;
			cache.concurrentLoadingCount = 0;
			if (cache.onLoadFinish != null)
				throw new Exception("cache.onLoadFinish should be null, got " + cache.onLoadFinish.ToString());

			cache.onLoadFinish += onLoadFinish;

			//加载好 AssetBundle 后执行这段
			Action<bool, AssetBundle, ECAssetBundleHeader, bool> onAssetBundleOK = (bLoadNew, assetBundle, assetDepends, async) =>
			{
				if (assetBundle == null)
				{
					Debug.LogWarning("Failed to load assetbundle file: " + path);

					cache.asset.Target = null;
					CacheFinishLoading(cache, null);
					return;
				}

				cache.SetAssetBundle(assetBundle);
				cache.assetDepends = assetDepends;

				//加载好所有依赖后执行这段,asset 可为空 (此时加载 assetBundle.mainAsset)
				Action<UnityObject> onDependsOK = (manuallyLoadedAsset) =>
				{
					//加载 Asset
					if (cache.AssetBundle == null)
						Debug.LogWarning("asset bundle is null when loading asset: " + path);

                    Action<UnityObject> onAssetLoaded = (mainAsset) =>    //Load asset 后调用
                    {
						//ReloadProperty(asset);
						
                        if (mainAsset == null)
                            Debug.LogError("Failed to load main asset of: " + path);

						Boolean bInCache = (cache.Asset != null);

                        var resourceAsset = mainAsset;
                        cache.asset.Target = resourceAsset;

                        if (resourceAsset != null && !bInCache && Instance.ShouldKeepCache(cache))
                        {
                            //!bInCache 即首次加载才需记录
                            Instance.m_donotReleaseAssetHolder.Add(resourceAsset);
                        }

						if (m_bEnableLog)
							Log("LoadAsset finish: " + path + "@ " + Time.realtimeSinceStartup);

                        if (resolveLevel <= ResolveLevel.None && (assetDepends.option & ECAssetBundleHeader.BundleOption.ManuallyResolve) == ECAssetBundleHeader.BundleOption.ManuallyResolve)
                        {
                            //cache.UnloadAssetBundle();	//Unload后好像有bug
                        }

						CacheFinishLoading(cache, resourceAsset);
                    };

					if (manuallyLoadedAsset != null)
					{
						onAssetLoaded(manuallyLoadedAsset);
					}
					else if (!bLoadNew && cache.Asset != null && !(cache.Asset is Material))
					{
					    onAssetLoaded(cache.Asset);
					}
					else
					{
						if (async || EnablePauseFlag)
						{
							ResourceLoader.GetTaskQueue().AddCoroutineInMainThread(AsyncLoadAsset(assetBundle, onAssetLoaded, path));
						}
						else
						{
                            ////checkres(path, typeof(Texture), dependLevel);
							CheckDependBundlesInCache(path);
							UnityObject mainAsset = assetBundle.Load("1");
							if (mainAsset == null)
								Debug.LogWarning("Failed to Load asset with name '1' from: " + path);
						
							if (m_bEnableLog)
								Log("AssetBundle.Load finish: " + path + "@ " + Time.realtimeSinceStartup);

							ReloadProperty(mainAsset);

							onAssetLoaded(mainAsset);
						}
					}
				};

				//开始加载所有依赖
                if (assetDepends == null || assetDepends.deps.Length == 0)	//无依赖
				{
					onDependsOK(null);
				}
				else	//有依赖
				{
                    ////var CurPath = path;
					var specialType = assetDepends.specialType;
                    Int32 leftDependsCount = assetDepends.deps.Length;

					if (specialType == ECAssetBundleHeader.BundleSpecialType.Material)	//特殊处理 Material		//TODO 移到 assetDepends 中处理
					{
						var dependAssets = new UnityObject[assetDepends.deps.Length];

						//material 的依赖加载完毕,手动设置贴图
						Action onMaterialDependsOK = ()=>
						{
							Material matAsset = assetBundle.Load("1") as Material;
							for (Int32 iDepend=0; iDepend<assetDepends.deps.Length; ++iDepend)
							{
								var depend = assetDepends.deps[iDepend];

								if (!String.IsNullOrEmpty(depend.name))
								{
									Texture tex = dependAssets[iDepend] as Texture;
									matAsset.SetTexture(depend.name, tex);
								}
							}

							ReloadProperty(matAsset);
							onDependsOK(matAsset);
						};

						for (Int32 iDepend=0; iDepend<assetDepends.deps.Length; ++iDepend)
						{
							Int32 dependIndex = iDepend;
							var depend = assetDepends.deps[dependIndex];

					        //Material 手动加载贴图
							if (!String.IsNullOrEmpty(depend.name))
							{
								LoadOrResolveResource(bAsync, depend.path, syncIO, createImmediate, ResolveLevel.None, (dependAsset)=>
								{
									PromptIfLoadDependFailed(path, dependAsset);

									dependAssets[dependIndex] = dependAsset;
									--leftDependsCount;

									if ((dependAsset as Texture) == null)
									{
										Debug.LogError("Failed to load texture bundle: " + depend.path + " for material: " + path);
									}

									if (leftDependsCount == 0)	//已加载所有依赖项
									{
										onMaterialDependsOK();
									}
								}, dependLevel+1, parentPath);
							}
							else		//其他依赖正常加载
							{
								LoadOrResolveResource(bAsync, depend.path, syncIO, createImmediate, IncreaseResolveLevel(resolveLevel), (dependAsset)=>		//TODO 去重
								{
									PromptIfLoadDependFailed(path, dependAsset);

									--leftDependsCount;
									if (leftDependsCount == 0)	//已加载所有依赖项
									{
										onMaterialDependsOK();
									}
								}, dependLevel+1, parentPath);
							}
					    }
					}
					else	//通用处理
					{
						foreach (var depend_ in assetDepends.deps)
						{
							var depend = depend_;	//创建新的局部变量
							LoadOrResolveResource(bAsync, depend.path, syncIO, createImmediate, IncreaseResolveLevel(resolveLevel), (dependAsset)=>
							{
								PromptIfLoadDependFailed(path, dependAsset);

								--leftDependsCount;
								if (leftDependsCount == 0)	//已加载所有依赖项
								{
									onDependsOK(null);	//尽量先加载依赖
								}
							}, dependLevel+1, parentPath);
						}
					}
				}
			};

			if (cache.AssetBundle != null)	//有缓冲
			{
				onAssetBundleOK(false, cache.AssetBundle, cache.assetDepends, cache.createFromFile);
			}
			else
			{
				Action<AssetBundle, ECAssetBundleHeader, bool> onLoadBundleFinished = (assetBundle, assetDepends, createfromfile)=>
				{
                    cache.createFromFile = createfromfile;
					if (m_bEnableLog)
						Log("LoadAssetBundle finish: " + path + "@ " + Time.realtimeSinceStartup);
                    onAssetBundleOK(true, assetBundle, assetDepends, createfromfile);
				};

				if (m_bEnableLog)
					Log("LoadAssetBundle begin: " + path + "@ " + Time.realtimeSinceStartup);

				if (bAsync)
				{
					ResourceLoader.AsyncLoadAssetBundle(path, syncIO, createImmediate, onLoadBundleFinished);
				}
				else
				{
					ResourceLoader.LoadAssetBundleImmediate(path, onLoadBundleFinished);
				}
			}
		}
Beispiel #2
0
		private static UnityObject GetResourceInCache(String path, ResolveLevel resolveLevel, out AssetCache cache)
		{
			cache = null;

			if (path == null)
				return null;

			if (resolveLevel > ResolveLevel.None)		//如果非ResolveLevel.None,不能直接返回此值,因为它的依赖还未 Resolve
				return null;

			path = UnifyPath(path);

			if (!Instance.m_assetCacheMap.TryGetValue(path, out cache))		//缓存中无任何记录
			{
				return null;
			}

			var asset = cache.GetAssetIfReady();
			if (!(asset is Material) || MakeSureIsMaterialAndHasAllTexture(cache))
			{
				return asset;
			}
			else
			{
				return null;
			}
		}
Beispiel #3
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="bAsync">是否异步加载</param>
		/// <param name="path"></param>
		/// <param name="syncIO"></param>
		/// <param name="createImmediate"></param>
		/// <param name="resolveLevel"></param>
		/// <param name="onLoadFinish"></param>
		/// <param name="dependLevel">第几层依赖,用于判断是否由最上层接口直接调用 (处理排队,需参考bAsync)</param>
		private static void LoadOrResolveResource(Boolean bAsync, String path, Boolean syncIO, Boolean createImmediate, ResolveLevel resolveLevel, Action<UnityObject> onLoadFinish, Int32 dependLevel, String parentPath)
		{
			path = UnifyPath(path);

			Action<UnityObject> onLoadFinishEx;
			if (dependLevel == 0)	//最上级需减少资源依赖计数
			{
				IncLoadingResourceCount();
				onLoadFinishEx = (asset)=>
				{
					AssetCache cache = Instance.m_assetCacheMap[path];
					Instance.DecDependedLoadingCountRecursively(cache);
					Instance.RefreshLRUAccessTimeRecursively(cache);
					DecLoadingResourceCount();
					onLoadFinish(asset);
				};
			}
			else
			{
				onLoadFinishEx = onLoadFinish;
			}

			//与 ResourceLoader 共用一个 TaskQueue,以控制总加载用时
			if (bAsync)
			{
				if (IsUnloadingUnusedAssets)
				{
					ResourceLoader.GetTaskQueue().AddCoroutineInMainThread(WaitForUnloadUnusedAssets(()=>
						LoadOrResolveResourceInternal(bAsync, path, syncIO, createImmediate, resolveLevel, onLoadFinishEx, dependLevel, parentPath)));
				}
				else
				{
					ResourceLoader.GetTaskQueue().AddActionInMainThread(()=>
						LoadOrResolveResourceInternal(bAsync, path, syncIO, createImmediate, resolveLevel, onLoadFinishEx, dependLevel, parentPath));
				}
			}
			else
			{
				LoadOrResolveResourceInternal(bAsync, path, syncIO, createImmediate, resolveLevel, onLoadFinishEx, dependLevel, parentPath);
			}
		}
Beispiel #4
0
		/// <summary>
		/// 提升一级,加载自身依赖时,应提升级别
		/// </summary>
		private static ResolveLevel IncreaseResolveLevel(ResolveLevel level)
		{
			return ResolveLevel.All;	//有点问题,只好一步到位
		}
Beispiel #5
0
		private static void AsyncLoadOrResolveResourceInternal(String path, Boolean syncIO, Boolean createImmediate, ResolveLevel resolveLevel, Action<UnityObject> onLoadFinish)
		{
			//如果已有缓存
			AssetCache cache;
			UnityObject assetInCache = GetResourceInCache(path, resolveLevel, out cache);
			if (assetInCache != null)
			{
				if (m_bEnableLog)
					m_lastAsyncLoadBeginTime = -1;

				Instance.RefreshLRUAccessTimeRecursively(cache);

				LogAsyncLoadFinish(path);
				//AsyncFinishLoading(() => ProtectedOnLoadFinish(path, onLoadFinish, assetInCache));	//不又限了
				ProtectedOnLoadFinish(path, onLoadFinish, assetInCache);
				return;
			}

			LoadOrResolveResource(true, path, syncIO, createImmediate, resolveLevel, onLoadFinish, 0, "");
			return;
		}
Beispiel #6
0
		private static void AsyncLoadOrResolveResourceInQueue(String path, Boolean syncIO, Boolean createImmediate, ResolveLevel resolveLevel, Action<UnityObject> onLoadFinish, Action<String> onLoadOneBundle)
		{
			if (m_bEnableLog)
			{
				//var onLoadFinishOrigin = onLoadFinish;
				//onLoadFinish = (asset) =>
				//    {
				//        Log(String.Format("AsyncLoad callback: {0}", path));
				//        onLoadFinishOrigin(asset);
				//    };
			}

			//如果已有缓存,不排队
			UnityObject assetInCache = GetResourceInCache(path, resolveLevel);
			if (assetInCache != null)
			{
				if (m_bEnableLog)
					m_lastAsyncLoadBeginTime = -1;

				LogAsyncLoadFinish(path);
				//AsyncFinishLoading(() => ProtectedOnLoadFinish(path, onLoadFinish, assetInCache));	//不又限了
				ProtectedOnLoadFinish(path, onLoadFinish, assetInCache);
				return;
			}

			//如果可能是同步加载,不排队
			if (true || /*试试*/ syncIO && createImmediate)
			{
				LoadOrResolveResource(true, path, syncIO, createImmediate, resolveLevel, onLoadFinish, onLoadOneBundle, 0);
				return;
			}

			Action<UnityObject> onLoadFinishInQueue = (asset)=>
				{
					LogAsyncLoadFinish(path);
					//AsyncFinishLoading(()=>onLoadFinish(asset));	//不又限了
					onLoadFinish(asset);

					m_loadRequestQueue.Dequeue();
					BeginLoadResourceQueue();
				};

			m_loadRequestQueue.Enqueue(new LoadResourceRequest {path=path, syncIO=syncIO, createImmediate=createImmediate, resolveLevel=resolveLevel, onLoadFinish=onLoadFinishInQueue, onLoadOneBundle=onLoadOneBundle});
			if (m_loadRequestQueue.Count == 1)
			{
				BeginLoadResourceQueue();
			}
		}
Beispiel #7
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="bAsync">是否异步加载</param>
		/// <param name="path"></param>
		/// <param name="syncIO"></param>
		/// <param name="createImmediate"></param>
		/// <param name="resolveLevel"></param>
		/// <param name="onLoadFinish"></param>
		/// <param name="onLoadOneBundle">每真正加载一个Bundle文件就调用一次。可为null</param>
		/// <param name="dependLevel">第几层依赖,用于判断是否由最上层接口直接调用 (处理排队,需参考bAsync)</param>
		private static void LoadOrResolveResource(Boolean bAsync, String path, Boolean syncIO, Boolean createImmediate, ResolveLevel resolveLevel, Action<UnityObject> onLoadFinish, Action<String> onLoadOneBundle, Int32 dependLevel)
		{
			path = UnifyPath(path);

			Action<UnityObject> onLoadFinishEx;
			if (dependLevel == 0)	//最上级需减少资源依赖计数
			{
				onLoadFinishEx = (asset)=>
				{
					AssetCache cache = Instance.m_assetCacheMap[path];
					Instance.DecDependedLoadingCountRecursively(cache);
					onLoadFinish(asset);
				};
			}
			else
			{
				onLoadFinishEx = onLoadFinish;
			}

			//与 ResourceLoader 共用一个 TaskQueue,以控制总加载用时
			ResourceLoader.GetTaskQueue().AddActionInMainThread(()=>
				LoadOrResolveResourceInternal(bAsync, path, syncIO, createImmediate, resolveLevel, onLoadFinishEx, onLoadOneBundle, dependLevel));
		}
Beispiel #8
0
		private static UnityObject GetResourceInCache(String path, ResolveLevel resolveLevel)
		{
			if (path == null)
				return null;

			if (resolveLevel > ResolveLevel.None)		//如果非ResolveLevel.None,不能直接返回此值,因为它的依赖还未 Resolve
				return null;

			path = UnifyPath(path);

			AssetCache cache;
			if (!Instance.m_assetCacheMap.TryGetValue(path, out cache))		//缓存中无任何记录
			{
				return null;
			}

			return cache.GetAssetIfReady();
		}