/// <summary> /// 强制卸载指定资源(不管AB加载后属于哪一种类型,强制卸载) /// </summary> /// <param name="abname"></param> public void forceUnloadSpecificResource(string abname) { ResourceLoadType resourceloadtype = ResourceLoadType.NormalLoad; AbstractResourceInfo arinfo = null; foreach (var loadedabinfomap in mAllLoadedResourceInfoMap) { if (arinfo != null) { break; } foreach (var loadedabinfo in loadedabinfomap.Value) { if (loadedabinfo.Key.Equals(abname)) { arinfo = loadedabinfo.Value; resourceloadtype = loadedabinfomap.Key; break; } } } if (arinfo != null) { mAllLoadedResourceInfoMap[resourceloadtype].Remove(arinfo.AssetBundleName); arinfo.dispose(); ResourceLogger.log(string.Format("AB资源 : {0}已强制卸载!", abname)); } else { ResourceLogger.logErr(string.Format("AB资源 : {0}未被加载,无法强制卸载!", abname)); } }
/// <summary> /// 异步加载场景 /// </summary> /// <param name="scenename"></param> public void loadSceneAync(string scenename) { // 预加载资源类型需要在切换场景前卸载掉,切换场景后可能有新的预加载资源加载进来 ResourceModuleManager.Singleton.unloadAllUnsedPreloadLoadedResources(); // 场景资源计数采用手动管理计数的方式 // 切场景时手动计数减1 // 加载时手动计数加1,不绑定对象 if (mCurrentSceneARI != null) { mCurrentSceneARI.release(); mCurrentSceneARI = null; } ResourceModuleManager.Singleton.requstResource( scenename, (abi) => { mCurrentSceneARI = abi; mCurrentSceneARI.retain(); SceneManager.LoadSceneAsync(scenename); }, ResourceLoadType.NormalLoad, ResourceLoadMethod.Async); }
/// <summary> /// 加载AB依赖文件信息完成回调 /// </summary> /// <param name="ari"></param> private void onLoadAllDpInfoComplete(AbstractResourceInfo ari) { mAssetBundleDpMap.Clear(); var abi = ari as AssetBundleInfo; if (abi.Bundle == null) { Debug.LogError("找不到ab依赖配置文件"); return; } //修改成读AssetBundleManifest方式 AssetBundleManifest manifest = abi.loadAsset <AssetBundleManifest>(AssetBundlePath.DependencyAssetName); if (manifest == null) { Debug.Log(string.Format("Failed to load {0}.manifest!", AssetBundlePath.DependencyAssetName)); return; } var allabnames = manifest.GetAllAssetBundles(); foreach (var abname in allabnames) { var abdeparray = manifest.GetAllDependencies(abname); mAssetBundleDpMap[abname] = abdeparray; } Debug.Log("AB依赖文件信息加载成功!"); }
/// <summary> /// 同步加载场景 /// </summary> /// <param name="scenename"></param> public void loadSceneSync(string scenename) { // 预加载资源类型需要在切换场景前卸载掉,切换场景后可能有新的预加载资源加载进来 ModuleManager.Singleton.getModule <ResourceModuleManager>().unloadAllUnsedPreloadLoadedResources(); // 场景资源计数采用手动管理计数的方式 // 切场景时手动计数减1 // 加载时手动计数加1,不绑定对象 if (mCurrentSceneARI != null) { mCurrentSceneARI.release(); mCurrentSceneARI = null; } // 减掉场景计数后,切换场景前强制卸载所有不再使用的正常加载的Unsed资源(递归判定释放) ModuleManager.Singleton.getModule <ResourceModuleManager>().unloadAllUnsedNormalLoadedResources(); ModuleManager.mSingleton.getModule <ResourceModuleManager>().requstResource( scenename, (abi) => { mCurrentSceneARI = abi; mCurrentSceneARI.retain(); }); SceneManager.LoadScene(scenename); }
/// <summary> /// 同步加载场景 /// </summary> /// <param name="scenepath"></param> public void loadSceneSync(string scenepath) { // 预加载资源类型需要在切换场景前卸载掉,切换场景后可能有新的预加载资源加载进来 ResourceModuleManager.Singleton.unloadAllUnsedPreloadLoadedResources(); // 场景资源计数采用手动管理计数的方式 // 切场景时手动计数减1 // 加载时手动计数加1,不绑定对象 if (mCurrentSceneARI != null) { mCurrentSceneARI.release(); mCurrentSceneARI = null; } // 减掉场景计数后,切换场景前强制卸载所有不再使用的正常加载的Unsed资源(递归判定释放) ResourceModuleManager.Singleton.unloadAllUnsedNormalLoadedResources(); ResourceModuleManager.Singleton.requstResource( scenepath, (abi) => { mCurrentSceneARI = abi; mCurrentSceneARI.retain(); }); var scenename = Path.GetFileNameWithoutExtension(scenepath); SceneManager.LoadScene(scenename); }
/// <summary> /// 播放背景音乐 /// </summary> public void onPlayBGM() { DIYLog.Log("onPlayBGM()"); if (mBGMAudioSource != null) { //背景音效是挂载GameLaucher上会导致永远无法满足卸载条件,所以需要手动移除对象绑定 if (mCurrentBGMARI != null) { mCurrentBGMARI.releaseOwner(mBGMAudioSource); } mRMM.requstResource("backgroundmusic", (ari) => { mCurrentBGMARI = ari; var clip = ari.getAsset <AudioClip>(mBGMAudioSource, "backgroundmusic"); mBGMAudioSource.clip = clip; mBGMAudioSource.loop = true; mBGMAudioSource.Play(); }); } else { DIYLog.LogError("背景音乐组件为空,无法播放!"); } }
/// <summary> /// 对应AB卸载回调 /// </summary> /// <param name="ari"></param> private static void onABUnloaded(AbstractResourceInfo ari) { var abi = ari as AssetBundleInfo; //AB卸载数据统计 if (ResourceLoadAnalyse.Singleton.ResourceLoadAnalyseSwitch) { ResourceLoadAnalyse.Singleton.addResourceUnloadedTime(abi.AssetBundleName); } // AB卸载时ABAssetBundleInfo回收时回收重用 AssetBundleInfoFactory.recycle(abi); }
/// <summary> /// 对应资源卸载回调 /// </summary> /// <param name="ari"></param> private static void onResourceUnloaded(AbstractResourceInfo ari) { var adi = ari as AssetDatabaseInfo; //资源卸载数据统计 if (ResourceLoadAnalyse.Singleton.ResourceLoadAnalyseSwitch) { ResourceLoadAnalyse.Singleton.addResourceUnloadedTime(adi.AssetBundleName); } // 资源卸载时资源AssetDatabaseInfo回收时回收重用 AssetDatabaseInfoFactory.recycle(adi); }
/// <summary> /// 显示一个AssetBundleInfo的信息 /// </summary> /// <param name="abi"></param> private void displayOneAssetBundleInfoUI(AbstractResourceInfo abi) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(string.Format("资源名 : {0}", abi.AssetBundlePath), GUILayout.Width(500.0f)); EditorGUILayout.LabelField(string.Format("是否就绪 : {0}", abi.mIsReady), GUILayout.Width(100.0f)); EditorGUILayout.LabelField(string.Format("引用计数 : {0}", abi.RefCount), GUILayout.Width(100.0f)); EditorGUILayout.LabelField(string.Format("最近使用时间 : {0}", abi.LastUsedTime), GUILayout.Width(150.0f)); EditorGUILayout.LabelField(string.Format("依赖引用对象列表 : {0}", abi.ReferenceOwnerList.Count == 0 ? "无" : string.Empty), GUILayout.Width(150.0f)); foreach (var refowner in abi.ReferenceOwnerList) { if (refowner.Target != null) { EditorGUILayout.ObjectField((UnityEngine.Object)refowner.Target, typeof(UnityEngine.Object), true, GUILayout.Width(200.0f)); } } EditorGUILayout.EndHorizontal(); }
/// <summary> /// 播放背景音乐 /// </summary> /// <param name="respath">资源路径</param> /// <param name="loop">是否循环播放</param> public void playBGM(string respath, bool loop = true) { //背景音效是挂载DontDestroyOnLoad上会导致永远无法满足卸载条件,所以需要手动移除对象绑定 if (mCurrentBGMARI != null) { mCurrentBGMARI.releaseOwner(mBGMAudioSource); } var assetname = Path.GetFileName(respath); ResourceModuleManager.Singleton.requstResource(respath, (ari) => { mCurrentBGMARI = ari; var clip = ari.getAsset <AudioClip>(mBGMAudioSource, assetname); mBGMAudioSource.clip = clip; mBGMAudioSource.loop = loop; mBGMAudioSource.Play(); }); }
/// <summary> /// 依赖AB加载完成回调 /// </summary> /// <param name="resinfo">ab加载信息</param> private void onDepABLoadComplete(AbstractResourceInfo resinfo) { var abinfo = resinfo as AssetBundleInfo; ResourceLogger.log(string.Format("依赖AB:{0}加载成功!", abinfo.AssetBundleName)); mDepAssetBundleInfoList.Add(abinfo); #if UNITY_EDITOR //Editor模式下的调试功能 // 移除已经加载过的,存储来测试查看用 mUnloadedAssetBundleName.Remove(abinfo.AssetBundleName); #endif mLoadedDepABCount++; // 作为依赖AB时并不会触发getAsset || instantiateAsset之类的接口, // 依赖于Unity加载依赖AB自动还原的机制,所以这里我们需要手动更新AB资源的最近使用时间 abinfo.updateLastUsedTime(); if (mLoadedDepABCount == mDepABCount) { allABLoadedComplete(); } }
/// <summary> /// 播放背景音乐 /// </summary> /// <param name="resname">资源名</param> /// <param name="assetname">Asset名</param> /// <param name="loop">是否循环播放</param> public void playBGM(string resname, string assetname = null, bool loop = true) { //背景音效是挂载DontDestroyOnLoad上会导致永远无法满足卸载条件,所以需要手动移除对象绑定 if (mCurrentBGMARI != null) { mCurrentBGMARI.releaseOwner(mBGMAudioSource); } if (string.IsNullOrEmpty(assetname)) { assetname = resname; } ResourceModuleManager.Singleton.requstResource(resname, (ari) => { mCurrentBGMARI = ari; var clip = ari.getAsset <AudioClip>(mBGMAudioSource, assetname); mBGMAudioSource.clip = clip; mBGMAudioSource.loop = loop; mBGMAudioSource.Play(); }); }
/// <summary> /// AB信息根据最近使用时间排序 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> private int ABILastUsedTimeSort(AbstractResourceInfo a, AbstractResourceInfo b) { return(a.LastUsedTime.CompareTo(b.LastUsedTime)); }