赞
踩
在Unity中,异步加载资源是一种优化游戏性能的重要手段,特别是在处理大型资源或需要平滑过渡的场景时。以下是关于Unity中异步加载资源的内容总结:
Resources.LoadAsync
:与Resources.Load
类似,但以异步方式加载资源。例如,Resources.LoadAsync<GameObject>("Cube")
。Resources.LoadAsync
基本用法:Resources.LoadAsync
返回一个ResourceRequest
对象,通过该对象可以检查加载进度和获取加载结果。因为加载资源分为两个阶段:加载中和加载完毕
示例:
public class LoadSource : MonoBehaviour { // 异步加载数据 // 加载图片 private Texture texture; private void Start() { MyAsychonizedLoad(); } void MyAsychonizedLoad() { // 异步加载--会消耗帧, 所以有很多资源的时候需要写一个加载的进度条 ResourceRequest re = Resources.LoadAsync<Texture>("Pictures/Picture"); // 是否加载结束 re.completed += ResourceCompleted; // 打印帧数 Debug.Log(Time.frameCount); } // 加载完毕回调函数 private void ResourceCompleted(AsyncOperation obj) { Debug.Log("资源加载完毕"); // 打印帧数 Debug.Log(Time.frameCount); // 对资源赋值 // 先类型转换 在赋值 ResourceRequest rq = obj as ResourceRequest; if (rq != null) { texture = rq.asset as Texture; } } // 测试加载好的图片 private void OnGUI() { if (texture != null) // 加载中的时候texture还是nuLl的 { GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), texture); } } }
ResourceRequest
和 协程Coroutine
都有继承了YieldInstruction
这个类. 由于加载资源是从加载中到加载完毕,是需要消耗一定的时间,这个时间我们不知道是多少,这取决于内存的大小和资源的大小. 而yeild return
紧紧跟着的内容可以是 null 1 2 自定类, 等待时间等. 因此,利用等待时间来加载资源.using System.Collections; using System.Collections.Generic; using UnityEngine; public class LoadResourcesAsychonized: MonoBehaviour { // 异步加载数据 -- 加载图片 private Texture texture; private void Start() { // 异步加载--协程模式加载 StartCoroutine(LoadOver()); StartCoroutine(LoadOverDetial()); } // 使用协程加载资源 IEnumerator LoadOver() { // 加载资源--图片 ResourceRequest rq = Resources.LoadAsync<Texture>("Pictures/Picture"); // ResourceRequest翻译为请求的资源- //该资源有很多信息: 是否加载完毕,加载优先级,当前加载进度,加载的资源,场景加载好就激活该资源(bool allowSceneActivation) // 打印帧数 Debug.Log(Time.frameCount); // 加载完毕 yield return rq; // 加载完毕继续执行, 为什么yield return rq呢? 因为ResourceRequest继承了AsyncOperation // 而AsyncOperation 继承了 YieldInstruction 且协程Coroutine中也是继承了 YieldInstruction // 所以大家继承了同一个类 当你使用 yield return rq; 时, // 你实际上是在告诉协程:“在这里暂停执行,直到 rq 这个异步操作完成。” // 这意味着协程会在这里等待,直到资源加载完成。 // 一旦资源加载完成,协程就会从 yield return 语句的下一条语句继续执行。 // 打印帧数 Debug.Log(Time.frameCount); // 资源加载完毕后,继续执行 texture = rq.asset as Texture; // 将资源转换为我们需要资源的类型 } // 协程异步加载详解 IEnumerator LoadOverDetial() { // 加载资源 ResourceRequest rq = Resources.LoadAsync<Texture>("Pictures/Picture"); // 打印帧数 Debug.Log(Time.frameCount); // 还可以获得加载的进度,是否加载完毕等数据 while (!rq.isDone) { Debug.Log("资源加载优先级" + rq.priority); Debug.Log("资源加载进度" + rq.progress); yield return null; } texture = rq.asset as Texture; } // 测试加载的资源--屏幕上绘制图片 private void OnGUI() { if (texture != null) { GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), texture); } } }
现在需要使用一个异步加载资源的单例类, 其他类中可以直接调用该方法实现加载资源,不用手动写回调函数或者自己开协程加载资源.
知识点: 单例 + 异步加载 + 协程 + 委托/事件
单例类的基本思路:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public class ResourceLoadManager : MonoBehaviour { // 单例异步加载数据管理器--给外部一个方法用于加载资源 // private static ResourceLoadManager instance = new ResourceLoadManager(); private static ResourceLoadManager instance; // 单例部分(继承自MonoBehaviour和不继承的) private ResourceLoadManager() { } public static ResourceLoadManager Instance { get { return instance; } } private void Awake() // 继承自MonoBehaviour的类,需要使用Awake来初始化数据 { instance = this; } // 普通异步加载 + 回调函数(用来资源加载完毕时候的逻辑,赋值之类的) public void LoadResourceAsynchionzed<T>(string sourceName, UnityAction<T> callBack) where T : Object { // 加载资源 ResourceRequest rq = Resources.LoadAsync<T>(sourceName); // 加载完毕调用回调函数 rq.completed += (a) => // 这里的a实际上是AsyncOperation的实例 拉姆达函数 { // 调用外部的回调函数 -- 转换资源 callBack((a as ResourceRequest).asset as T); // 将加载好的资源通过外部回调函数返回 Debug.Log("资源转换成功,并已返回给对象"); }; } // 使用协程加载 public void LoadResourceAsynchionzedCoroutine<T>(string sourceName, UnityAction<T> callBack) where T : Object { // 开启协程 StartCoroutine(LoadSource<T>(sourceName, callBack)); } // 协程 IEnumerator LoadSource<T>(string sourceName, UnityAction<T> callBack) where T: Object { // 加载资源中 ResourceRequest rq = Resources.LoadAsync<T>(sourceName); yield return rq; // 资源加载好了--转换资源 callBack(rq.asset as T); } }
在需要加载资源的地方调用单例中的加载资源的方法即可
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LoadResourcesTest : MonoBehaviour { private Texture texture; // 图片资源 private void Start() { // 调用加载函数 -- 拉姆达表达式 /* ResourceLoadManager.Instance.LoadResourceAsynchionzed<Texture>("Pictures/Picture", (obj) => { texture = obj; });*/ // 普通单例异步加载 -- 加载图片资源 // ResourceLoadManager.Instance.LoadResourceAsynchionzed<Texture>("Pictures/Picture", OnpictureLoaded); // 协程单例异步加载-- 加载图片资源 ResourceLoadManager.Instance.LoadResourceAsynchionzedCoroutine<Texture>("Pictures/Picture", OnPictureLoaded); } private void OnPictureLoaded(Texture loadedTexture) { texture = loadedTexture; } // 测试 private void OnGUI() { if (texture != null) { GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), texture); } } }
异步加载资源是Unity游戏开发中的重要技巧,能够显著提升游戏性能和用户体验。开发者应根据项目需求选择合适的异步加载方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。