欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > Unity--异步加载资源

Unity--异步加载资源

2025/4/19 18:20:51 来源:https://blog.csdn.net/qq_40669895/article/details/140112967  浏览:    关键词:Unity--异步加载资源

Unity–异步加载资源

0. 异步加载资源简介

在Unity中,异步加载资源是一种优化游戏性能的重要手段,特别是在处理大型资源或需要平滑过渡的场景时。以下是关于Unity中异步加载资源的内容总结:

1. 为什么使用异步加载

  • 避免卡顿:异步加载可以在不冻结游戏主线程的情况下加载资源,从而避免游戏过程中的卡顿。
  • 提高性能:在加载资源的同时,游戏可以继续运行,提高整体性能。

2. 异步加载方法

  • Resources.LoadAsync:与Resources.Load类似,但以异步方式加载资源。例如,Resources.LoadAsync<GameObject>("Cube")

3. 使用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);}}
    }

4. 使用协程来异步加载资源

  • 为什么使用协程来加载资源, 因为协程虽不是线程但是轻量级的线程,可以分担主线程的压力.
  • 为什么可以用协程来异步加载资源. 因为异步加载资源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);}}
}

5. 提取异步加载为单例类

现在需要使用一个异步加载资源的单例类, 其他类中可以直接调用该方法实现加载资源,不用手动写回调函数或者自己开协程加载资源.

知识点: 单例 + 异步加载 + 协程 + 委托/事件

单例类的基本思路:

  1. 传入要加载的资源的名称/路径,以及资源的类型
  2. 利用协程加载资源
  3. 资源加载好了要转换为对应的类型
  4. 转化好的资源需要返回给调用的地方
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);}}
}

6. 注意事项

  • 异步加载时应确保资源加载完成后再进行操作。
  • 注意资源的卸载,避免内存泄漏。

7. 结论

异步加载资源是Unity游戏开发中的重要技巧,能够显著提升游戏性能和用户体验。开发者应根据项目需求选择合适的异步加载方法。

版权声明:

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

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

热搜词