3、Unity【基础】Resources资源场景动态加载

2024-08-23 06:36

本文主要是介绍3、Unity【基础】Resources资源场景动态加载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

文章目录

  • 一、Resources资源动态加载
    • 1、Unity中特殊文件夹
      • 1、工程路径获取
      • 2、Resources资源文件夹
      • 3、StreamingAssets流动资源文件夹
      • 4、persistentDataPath持久数据文件夹
      • 5、Plugins插件文件夹
      • 6、Editor编辑器文件夹
      • 7、默认资源文件夹StandardAssets
    • 2、Resources同步加载
      • 1、Resources资源动态加载的作用
      • 2、常用资源类型
      • 3、资源同步加载【普通方法】
      • 4、资源同步加载【泛型方法】
    • 3、Resources异步加载
      • 1、Resources异步加载概念
      • 2、Resources异步加载方法
      • 思考 封装资源异步加载管理器
    • 4、Resources卸载资源
      • 1、Resources重复加载资源与内存
      • 2、如何手动释放掉缓存中的资源
  • 二、场景异步加载
    • 1、场景同步切换
    • 2、场景异步切换
      • 1、通过事件回调函数异步加载
      • 2、通过协程异步加载
      • 3、场景异步加载总结
      • 思考 封装场景管理器

一、Resources资源动态加载

1、Unity中特殊文件夹

1、工程路径获取

Application.dataPath //开发使用,打包后无效

2、Resources资源文件夹

路径获取:一般不获取
只能使用Resources相关API进行加载
可以用工程路径拼接获取路径print(Application.dataPath+"/Resources");
注意:
需要我们自己创建
作用:
资源文件夹
1.需要通过Resources相关API动态加载的资源需要放在其中
2.该文件夹下所有文件都会被打包
3.打包时Unity会对其压缩加密
4.该文件夹打包后只读只能通过Resources相关API加载

3、StreamingAssets流动资源文件夹

路径获取print(Application.streamingAssetsPath);
注意:
需要我们自已创建
作用:
流文件夹
1.打包出去不会被压缩励密,可以任由我们门摆布
2.移动平台只读,PC平台可读可写
3.可以放入一些需要自定义动态加载的初始资源

4、persistentDataPath持久数据文件夹

路径获取print(Application.persistentDataPath);
注意:
不需要我们自己创建
作用:
固定数据文件夹
1.所有平台都可读写
2.一般用于放置动态下载或者动态创建的文件,游戏中创建或者获取的文件都放在其中

5、Plugins插件文件夹

路径获取般不获取
注意:
需要我们自己创建
作用:
插件文件夹
不同平台的插件相关文件放在其中
比如放入Ios和Android平台的工具

6、Editor编辑器文件夹

路径获取:一般不获取
如果硬要获取可以用工程路径拼接
注意:
需要我们自己创建
作用:
编辑器文件夹
1.开发Unity编辑器时,编辑器相关脚本放在该文件夹中
2.该文件夹中内容不会被打包出去

7、默认资源文件夹StandardAssets

路劲获取:一般不获取
注意:
需要我们自己创建
作用:
默认资源文件夹
一般Unity自带资源都放在这个文件夹下
代码和资源优先被编译

2、Resources同步加载

1、Resources资源动态加载的作用

1.通过代码动态加载Resources文件夹下指定路径资源
2.避免繁锁的拖曳操作

2、常用资源类型

1.预设体对象 Gameobject
2.音效文件 AudioClip
3.文本文件 TextAsset
4.图片文件 Texture
5.其它类型 需要什么用什么类型
注意:
预设体对象加载需要实例化
其它资源加载一般直接用

3、资源同步加载【普通方法】

一个工程可以有多个Resources文件夹,打包时会自动整合在一起1.预设体对象 想要创建在场景上【实例化】第一步:要去加载设体的资源文件(本质上就是加载配置数据在内存中)Object obj = Resources.Load("Cube");第二步:如果想要在场景创建预设体一定是加载配置文件过后然后实例化Instantiate(obj);2.音效资源public AudioSource audioS;第一步:加载数据Object obj = Resources.Load("Music/BkMusic");第二步:使用数据,不需要实例化音效切片,只需要把数据赋值到正确的脚本上即可audioS.clip = obj as AudioClip;audioS.Play();3.文本资源
文本资源支持的格式
.txt.xml.bytes.json.html.csvTextAsset ta = Resources.Load("Txt/Test")as TextAsset;
文本内容print(ta.text);
字节数据组print(ta.bytes);4.图片private Texture tex;tex = Resources.Load("Tex/TestJPG") as Texture;private void OnGUI(){GUI.DrawTexture(new Rect(0, 0,100, 100),tex);}5.其它类型 需要什么类型就用什么类型就行6.问题:资源同名怎么办Resources.Load加载同名资源时,无法准确载出你想要的内容可以使用另外的API1.加载指定类型的资源tex = Resources.Load("Tex/TestJPG",typeof(Texture)) as Texture;ta = Resources.Load("Tex/TestJPG",typeof(TextAsset)) as TextAsset;2.加载指定名学的所有资源Object[] objs = Resources.LoadAll("Tex/TestJPG")foreach (Object item in objs){if(itemisTexture){}else if(item is TextAsset){}}

4、资源同步加载【泛型方法】

TextAsset ta = Resources.Load<TextAsset>("Tex/TestJPG");
tex = Resources.Load<Texture>("Tex/TestJPG");
例:bullet = Resources.Load<GameObject>("bullet"); //每次加载不会浪费内存,会消耗性能

3、Resources异步加载

1、Resources异步加载概念

在同步加载中
如果加载过大的资源可能会造成程序卡顿
卡顿的原因就是从硬盘上把数据读取到内存中是需要进行计算的
越大的资源耗时越长,就会造成掉顿卡顿Resources异步加载就是内部新开一个线程进行资源加载不会造成主线程卡顿

2、Resources异步加载方法

异步加载不能马上得到加载的资源,至少要等一帧
1、通过【异步加载】中的完成事件监听,使用加载的资源private Texture tex;private void LoadOver(AsyncOperation ao){print("加载完成");print(Time.frameCount); //测试查看帧//加载完成后使用asset,是资源对象tex = (ao as ResourceRequest).asset as Texture;}	void Start(){//Unity在内部就会去开一个线程进行资源下载//LoadAsync方法的返回值ResourceRequest里的asset;//ResourceRequest继承的AsyncOperation类有completed事件ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");//马上进行一个资源下载结束的一个事件函数监听rq.completed += LoadOver;print(Time.frameCount);}private void OnGUI(){if(tex!= null)GUI.DrawTexture(new Rect(0, 0, 100, 100), tex);}2、通过【协程】使用加载的资源StartCoroutine(Load());IEnumerator Load(){//【选代器函数】遇到yield return时就会停止执行之后的代码//然后【协程协调器】通过得到返回的值去判断下一次执行后面步骤的时间ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");//第一部分//Unity自动检测到异步加载资源yield return rq;打印进度while(!re.isDone){ //是否结束print(re.priority); //priority进度yield return null; //测试}//加载完毕后,Unity自动执行之后代码tex = rq.asset as Texture;
}
线程加载和协程异步加载【比较】
1.完成事件监听异步加载
写法简单
但只能在资源加载结束后进行处理
“线性加载”2.协程异步加载
好处:可以在协程中处理复杂逻辑,比如同时加载【多】个资源,比如进度条更新
坏处:写法稍麻烦
“并行加载” 思考:
理解为什么异步加载不能马上加载结束,为什么至少要等1顿
理解协程异步加载的原理

思考 封装资源异步加载管理器

请写一个简单的资源管理器:
提供统一的方法给外部用于资源异步加载,
外部可以传入委托用于当资源加载结束时使用资源

ResourcesMgr

using UnityEngine;
using UnityEngine.Events;public class ResourcesMgr
{private static ResourcesMgr instance = new ResourcesMgr();public static ResourcesMgr Instance => instance;private ResourcesMgr(){}/// <summary>/// 异步加载资源/// </summary>/// <param name="name">函数名</param>/// <param name="callBack">回调函数</param>public void AsyncLoadResources<T>(string name, UnityAction<T> callBack) where T : Object{ResourceRequest resReq = Resources.LoadAsync<T>(name);resReq.completed += (finish) =>{//参数finish是completed的值,事件completed是ResourceRequest的父类,所以://资源对象(finish as ResourceRequest).asset as TcallBack((finish as ResourceRequest).asset as T);};}}

Test_ResMgr

using UnityEngine;public class Test_ResMgr : MonoBehaviour
{private Texture tex;void Start(){//封装前代码ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");rq.completed += (v) =>{tex = (v as ResourceRequest).asset as Texture;};//封装后代码ResourcesMgr.Instance.AsyncLoadResources<Texture>("Tex/TestJPG", (obj) => { tex = obj; });}private void OnGUI(){if (tex != null) //避免异步加载有可能为空GUI.DrawTexture(new Rect(0, 0, 200, 100), tex);}
}

4、Resources卸载资源

1、Resources重复加载资源与内存

其实Resources加载一次资源过后
该资源就一直存放在内存中【作为缓存】
第二次加载时发现缓存中存在该资源会直接取出来进行使用
所以多次重复加载不会浪费内存
但是会浪费性能(每次加载都会去查找取出,始终伴随一些性能消耗)

2、如何手动释放掉缓存中的资源

1.卸载指定资源
Resources.UnloadAsset方法
注意
该方法不能释放Gameobiect对象因为它会用于实例化对象
它只能用于一些不需要实例化的内容比如图片和音效文本等
一般情况下很少单独使用它2.卸载未使用的资源
注意:
一般在过场景时和GC一起使用Resources.UnloadUnusedAssets(); GC.Collect();

二、场景异步加载

1、场景同步切换

SceneManager.LoadScene("Test") //在Build Settings添加切换场景
场景同步切换的缺点
在切换场景时
Unity会删除当前场景上所有对象,并且去加载下一个场景的相关信息
如果当前场景对象过多或者下一个场景对象过多,这个过程会非常的耗时、卡顿

2、场景异步切换

1、通过事件回调函数异步加载

场景异步加载和资源异步加载几乎一致,有两种方式
1.通过事件回调函数异步加载SceneManager.LoadSceneAsync("Test");void Start()
{AsyncOperation ao = SceneManager.LoadSceneAsync("Test");//异步加载完成后,使用逻辑ao.completed += (a) =>{print("加载完成");};ao.completed += LoadOver;
}
private void LoadOver(AsyncOperation ao)
{print("LoadOver");
}

2、通过协程异步加载

2.通过协程异步加载
需要注意的是:加载场景会把当前场景上没有特别处理的对象都删除了
所以协程中的部分逻辑可能是执行不了的
解决思路
让处理场景加载的脚本依附的对象,过场景时不被移除
void Start()
{DontDestroyOnLoad(gameObject); //挂载此脚本的对象过场景时不被移除StartCoroutine(LoadScene("Test"));
}IEnumerator LoadScene(string name)
{///第一步://异步加载场景AsyncOperation ao = SceneManager.LoadSceneAsync(name);//Unity内部的协程协调器发现是异步加载类型的返回对象那么就会//等待异步加载结束后会续执行选代器函数中后面的步骤print("异步加载中");//协程的好处是异步加载场景时我可以在加载的同时做一些别的逻辑yield return ao;//第二步骤:print("异步加载后");//比如我们门可以在异步加载过程中去更新进度条第一种 就是利用场景异步加载的进度去更新但是不是特别准确一般也不会直接用while(!ao.isDone){print(ao.progress);yield return null;} //离开循环后就会认为场景加载结束,可以把进度条顶满然后隐藏进度条第二种 就是根据你游戏的规则自己定义进度条变化的条件//场景加载结束更新20%进度//接着去加载场景中的其它信息//比如动态加载怪物//这时进度条再更新20%//动态加载场景模型//这时就认为加载结束了100%进度条//隐藏进度条
}

3、场景异步加载总结

场景异步加载和资源异步加载一样有两种方式1.通过事件回调函数 2.协程异步加载也们的优缺点表现和资源异步加载也是一样的
1.事件回调函数优点:写法简单,逻辑清晰缺点:只能加载完场景做一些事情不能再加载过程中处理逻辑
2.协程异步加载优点:可以在加载过程中处理逻辑,比如进度条更新等缺点:写法较为麻烦,要通过协程

思考 封装场景管理器

请写一个简单的场景管理器,
提供统一的方法给外部用于场景异步切换
外部可以传入委托用于当异步切换结束时执行某些逻辑

SceneMgr

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;public class SceneMgr
{private static SceneMgr instance;public static SceneMgr Instance => instance;public SceneMgr(){}public void LoadScene(string name, UnityAction action){AsyncOperation ao = SceneManager.LoadSceneAsync(name);//通过lambda表达式包裹一层,在内部直接调用外部传入的委托即可ao.completed += (a) => { action(); };}
}

Test_Scene

using UnityEngine;public class Test_Scene : MonoBehaviour
{void Start(){SceneMgr.Instance.LoadScene("Test", () => { print("加载完成"); });}
}

这篇关于3、Unity【基础】Resources资源场景动态加载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1098620

相关文章

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

java中VO PO DTO POJO BO DO对象的应用场景及使用方式

《java中VOPODTOPOJOBODO对象的应用场景及使用方式》文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它... 目录Java中VO PO DTO POJO BO DO对象的应用VO (View Object) - 视图对象

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

MyBatis延迟加载的处理方案

《MyBatis延迟加载的处理方案》MyBatis支持延迟加载(LazyLoading),允许在需要数据时才从数据库加载,而不是在查询结果第一次返回时就立即加载所有数据,延迟加载的核心思想是,将关联对... 目录MyBATis如何处理延迟加载?延迟加载的原理1. 开启延迟加载2. 延迟加载的配置2.1 使用

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节