您的位置:首页 > 娱乐 > 明星 > 【Unity开发】避免重复加载场景资产AB(AssetBundle)包的优化

【Unity开发】避免重复加载场景资产AB(AssetBundle)包的优化

2025/2/25 18:36:34 来源:https://blog.csdn.net/fuweipeng2012/article/details/141360881  浏览:    关键词:【Unity开发】避免重复加载场景资产AB(AssetBundle)包的优化

@[TOC](【Unity开发】避免重复加载场景资产AB(AssetBundle)包的优化)

项目需要远程加载场景AB包,并加载场景。

1、 初始方案

1.1 异步加载场景资产(获取AB包数据)

	public IEnumerator LoadAssetFromAB(string url, Action<AssetBundle> assetAB){yield return new WaitForSeconds(0.16f);using (UnityWebRequest webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url)){yield return webRequest.SendWebRequest();if (webRequest.result == UnityWebRequest.Result.Success){var bundle = DownloadHandlerAssetBundle.GetContent(webRequest);assetAB?.Invoke(bundle);}}}

1.2 异步加载场景(进入场景)

	// 异步加载远程AB场景public void LoadSceneFromAB(AssetBundle assetAB, string sceneName){// 启动异步线程加载场景StartCoroutine(AssetToScene(assetAB, sceneName));}// 异步远程AB场景迭代器private IEnumerator AssetToScene(AssetBundle assetAB, string sceneName){// 异步加载场景资产AsyncOperation  loadOperation = SceneManager.LoadSceneAsync(sceneName);yield return loadOperation;Debug.Log("应该到不了这里就直接转场了,那么AB资产包还在内存,下次就会报[重复加载]的异常");// 卸载内存中的assetAB资产(除了LoadScene创建出来的场景)assetAB.Unload(false);}

1.3 点击跳转场景

	public void GotoScene(ClickEvent evt){string sceneName = "myScene";char dsp = Path.AltDirectorySeparatorChar;string url = Application.dataPath + dsp + "scene" + dsp + sceneName;// 销毁所有未使用资产Resources.UnloadUnusedAssets();// 临时解决方案// 尝试直接加载AB场景 (避免AB资产已在内存时AB包重复报错)// The AssetBundle 'http://192.168.2.107:8080/level/Level1' can't be loaded because another AssetBundle with the same files is already loaded.SceneManager.LoadScene(sceneName);// 这里如果成功加载场景,不会走到下一步,// 前提是内存里有场景包 1、上次已经加载到内存没卸载 2、程序Build编译时Scenes In Build// Scene 'Level1' couldn't be loaded because it has not been added to the build settings or the AssetBundle has not been loaded.//To add a scene to the build settings use the menu File->Build Settings...// 远程异步加载AB场景资产StartCoroutine(_dataRestapi.LoadAssetFromAB(url, (assetAB) => {if (assetAB != null) {LoadSceneFromAB(assetAB, sceneName);}else{Debug.LogWarning("场景资产数据加载失败");}}));}

2、 优化方案

2.1 异步加载场景资产(获取AB包数据)

	public IEnumerator LoadAssetFromAB(string url, Action<AssetBundle> assetAB){yield return new WaitForSeconds(0.16f);using (UnityWebRequest webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url)){yield return webRequest.SendWebRequest();if (webRequest.result == UnityWebRequest.Result.Success){var bundle = DownloadHandlerAssetBundle.GetContent(webRequest);assetAB?.Invoke(bundle);}}}

2.2 异步加载场景(进入场景)

1 注册后处理事件 SceneManager.sceneLoaded += OnSceneLoaded;
2 删除永远不会被运行的 assetAB.Unload(false);

	// 异步加载远程AB场景public void LoadSceneFromAB(AssetBundle assetAB, string sceneName){// 启动异步线程加载场景StartCoroutine(AssetToScene(assetAB, sceneName));// 当新场景开始加载时注册事件 解决加载完成后处理事件SceneManager.sceneLoaded += OnSceneLoaded;}// 异步远程AB场景迭代器private IEnumerator AssetToScene(AssetBundle assetAB, string sceneName){// 异步加载场景资产AsyncOperation  loadOperation = SceneManager.LoadSceneAsync(sceneName);yield return loadOperation;}

2.3 点击跳转场景

删除尝试加载场景 SceneManager.LoadScene(sceneName);
因为不需要了,每次运行都是从远程获取最新的场景AB包

	public void GotoScene(ClickEvent evt){string sceneName = "myScene";char dsp = Path.AltDirectorySeparatorChar;string url = Application.dataPath + dsp + "scene" + dsp + sceneName;// 销毁所有未使用资产Resources.UnloadUnusedAssets();// 远程异步加载AB场景资产StartCoroutine(_dataRestapi.LoadAssetFromAB(url, (assetAB) => {if (assetAB != null) {LoadSceneFromAB(assetAB, sceneName);}else{Debug.LogWarning("场景资产数据加载失败");}}));}

2.4 增加场景加载后处理事件

保证场景加载完成后自动删除场景AB资产包

	// 场景加载后处理事件void OnSceneLoaded(Scene scene, LoadSceneMode mode){// 当新场景加载完成后,卸载内存中AssetBundle包(除了Load创建出来的对象/场景)_assetAB.Unload(false);// 注销事件,防止重复调用SceneManager.sceneLoaded -= OnSceneLoaded;}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com