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); } } }
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; } }
/// <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); } }
/// <summary> /// 提升一级,加载自身依赖时,应提升级别 /// </summary> private static ResolveLevel IncreaseResolveLevel(ResolveLevel level) { return ResolveLevel.All; //有点问题,只好一步到位 }
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; }
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(); } }
/// <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)); }
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(); }