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游戏开发中的重要技巧,能够显著提升游戏性能和用户体验。开发者应根据项目需求选择合适的异步加载方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/39842.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pycharm配置conda解释器

假如我新建了一个conda虚拟环境&#xff0c;名为python3.8

学校教室NTP电子钟时间是如何同步北京时间的?-讯鹏时钟

在学校教室里&#xff0c;NTP 电子钟精准地显示着时间&#xff0c;与北京时间保持高度同步&#xff0c;为师生们提供了可靠的时间参考。那么&#xff0c;它是如何做到这一点的呢&#xff1f; NTP 电子钟能够与北京时间同步&#xff0c;主要依赖于网络时间协议&#xff08;NTP&a…

【Python】从文本字符串中提取数字、电话号码、日期、网址的方法汇总(全!)

我们在做数据清洗的时候&#xff0c;有时候会遇到将一堆文本中提取我们需要的内容&#xff0c;最常见的是&#xff0c;从一大段文本中提取出数字、电话号码、日期、网址等。而在Python中&#xff0c;正则表达式re&#xff0c;则可以满足我们从文本中提取数字、电话号码和日期等…

一篇文章入门主成分分析PCA

文章目录 基本概念事件随机变量独立同分布离散型随机变量伯努利分布&#xff08;两点分布&#xff09;二项分布几何分布泊松分布 连续型随机变量正态分布 期望方差标准化协方差相关系数线性组合特征值和特征向量特征值分解对称矩阵的特征值分解 齐次线性方程组单位向量基向量矩…

钉钉机器人接入Dify工作流

实现钉钉机器人接入dify工作流&#xff0c;完成ai 流式问答 代码地址 有用的话点个star github地址 效果 配置使用 修改.env_template文件 为.env 设置.env文件内的环境变量 API_KEY: dify的api_keyAPI_URL: dify 的api接口CLIENT_ID : 钉钉机器人应用的idCLIENT_SECRET:钉…

松下护眼大路灯值得买吗?实测对比书客、松下、雷士三款热门护眼灯

松下护眼大路灯值得买吗&#xff1f;面对长时间的频繁用眼&#xff0c;选择一款可以提供宽广接近自然光的护眼大路灯&#xff0c;用了才知道有多香&#xff0c;而大路灯的选购也有讲究&#xff0c;在面对市面上的琳琅满目的护眼大路灯&#xff0c;怎么选好一款灯也是个大学问&a…

layui-页面布局

1.布局容器 分为固定和完整宽度 class layui-container 是固定宽度 layui-fluid是完整宽度

【Python网络通信】基于Bypy调用百度网盘api实现自动上传和下载网盘文件

网盘对于大家的生活工作可以说是息息相关&#xff0c;但是如果每天都重复去上传下载文件就会很浪费时间&#xff0c;所以有没有什么办法可以解放双手&#xff1f;那就是网盘接口&#xff0c;本文通过Bypy库实现百度网盘的自动上传和下载文件。 原创作者&#xff1a;RS迷途小书童…

修改van-toast文字大小样式

this.$toast({type:fail,message: 文件超过50M,className: toastWidth })样式不能写在scoped lang"scss"里面&#xff0c;样式会失效&#xff0c;只能写在style里面 <style> .toastWidth{min-width: 150px !important;line-height: 34px;font-size: 24px; } &…

Ubuntu20.04配置TurtleBot3 Waffle Pi远程控制

这里写目录标题 0. 机器人配置1. Ubuntu20.04配置TurtleBot3 Waffle Pi远程控制1.1 TurtleBot3 Waffle Pi端配置1.2 PC端配置1.2.1 安装turtlebot3的环境配置1.2.2 创建项目并安装Turtlebot31.2.3 配置环境变量 1.3 PC端与TurtleBot3进行通信1.3.1 PC端与机器人端互PING和SSH连…

【Axure视频教程】控制其他页面元件——动态面板案例

今天教大家在Axure制作控制其他页面元件--动态面板案例模板&#xff0c;我们可以在一个页面中控制另外一个页面的元件&#xff0c;案例中是通过点击不同的按钮&#xff0c;进入其他页面后显示对应的动态面板的状态页。该教程从0开始制作&#xff0c;手把手教学&#xff0c;无论…

pgrouting使用

pgRouting是一个为PostgreSQL和PostGIS提供路由功能的开源库&#xff0c;它支持复杂的图论算法&#xff0c;用于在地理网络中进行最短路径搜索。以下是pgRouting的一些应用实例。 注意事项&#xff1a; 1、路网表中的id、source、target必须是int类型&#xff0c;否则创建拓扑…

【论文解读】Multiagent Multitraversal Multimodal Self-Driving: Open MARS Dataset

Open MARS Dataset 摘要引言Dataset CurationVehicle SetupData CollectionDataset Statistics Benchmark Task and ModelPlace RecognitionNeural Reconstruction Experimental ResultsVisual Place RecognitionNeural Reconstruction Opportunities and Challenges结论 摘要 …

Python的列表list(与C++的vector对比学习)

一、前言 Python的列表list与C的vector很像&#xff0c;但也有很多不同之处&#xff0c;接下来我们将会通过C的vector对比学习列表list 二、相同点 都支持动态扩容&#xff0c;可以随时随地添加和删除元素下标访问时&#xff0c;第一个元素下标为0 三、不同点 Python的 list…

centos安装打包工具fpm

安装ruby环境 yum -y install ruby-devel gcc make rpm-build rubygems ruby安装fpm RubyGems是Ruby的一个包管理器,功能上类似于apt-get、yum等,所以我们需要通过RubyGems来安装fpm。 由于国外的源很慢,或者直接不能访问,需要将Ruby Gems源更换为国内的源。 添加阿里云…

vivado联合modelsim仿真

一. 编译Vivado仿真库 打开Vivado&#xff0c;Tools -> Compile Simulation Libraries 二. 设置仿真工具和库路径 因为新建工程的默认仿真工具是Vivado Simulator&#xff0c;所以要使用Modelsim仿真&#xff0c;每个新工程都要设置一次&#xff0c;方法如下&#xff1a; …

上海小程序开发需要进行定制开发吗?

随着互联网技术与移动设备的不断成熟&#xff0c;小程序也已普及到人们日常生活的方方面面。随着企业与互联网联结的愈发深入&#xff0c;小程序的开发可以为企业带来更高效的经营模式&#xff0c;降本增效。那么&#xff0c;上海小程序作为无需安装且开发门槛较低的应用&#…

【Python】Python中的常量与变量

常量与变量 导读一、新建项目二、常量2.1 字面常量2.2 特殊常量 三、变量3.1 变量的定义3.2 变量的命名3.2.1 关键字 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 在上一篇内容中我们详细介绍了Python环境的搭建过程&#xff0c;…

关于甲床过短如何养甲床的一些方法与建议

要使甲床变长&#xff0c;需要根据甲床短的具体原因来采取相应的措施。以下是一些常见的方法和建议&#xff1a; 一、针对先天性因素 无法改变&#xff1a;如果甲床短是由于先天性因素&#xff08;如遗传、环境影响&#xff09;导致的&#xff0c;一般无法直接改变其长度&…

AI目标检测算法详解

引言 目标检测&#xff08;Object Detection&#xff09;是计算机视觉中的一项重要任务&#xff0c;旨在识别和定位图像或视频中的物体。近年来&#xff0c;随着深度学习的发展&#xff0c;AI目标检测算法取得了显著的进展&#xff0c;被广泛应用于自动驾驶、智能监控、医疗影…