Unity基础3——Resources资源动态加载

news2025/2/9 1:55:16

一、特殊文件夹

(一)工程路径获取

// 注意 该方式 获取到的路径 一般情况下 只在 编辑模式下使用
// 我们不会在实际发布游戏后 还使用该路径
// 游戏发布过后 该路径就不存在了 
print(Application.dataPath);

(二)Resources 资源文件夹

// 路径获取:
// 一般不获取
// 只能使用Resources相关API进行加载
// 如果硬要获取 可以用工程路径拼接
print(Application.dataPath + "/Resources");

​ 注意:需要我们自己创建

​ 作用:资源文件夹

  1. 需要通过 Resources 相关 API 动态加载的资源需要放在其中

  2. 该文件夹下所有文件都会被打包出去

  3. 打包时 Unity 会对其压缩加密

  4. 该文件夹打包后只读 只能通过 Resources 相关 API 加载

(三)StreamingAssets 流动资源文件夹

// 路径获取:
print(Application.streamingAssetsPath);

​ 注意:需要我们自己将创建
​ 作用:流文件夹

  1. 打包出去不会被压缩加密,可以任由我们摆布

  2. 移动平台只读,PC 平台可读可写

  3. 可以放入一些需要自定义动态加载的初始资源

(四)PersistentDataPath 持久数据文件夹

// 路径获取:
print(Application.persistentDataPath);

​ 注意:不需要我们自己将创建
​ 作用:固定数据文件夹

  1. 所有平台都可读可写

  2. 一般用于放置动态下载或者动态创建的文件,游戏中创建或者获取的文件都放在其中

(五)Plugins 插件文件夹

​ 路径获取:一般不获取

​ 注意:需要我们自己将创建
​ 作用:插件文件夹
​ 不同平台的插件相关文件放在其中,比如 IOS 和 Android 平台

(六)Editor 编辑器文件夹

// 路径获取:
// 一般不获取
// 如果硬要获取 可以用工程路径拼接
print(Application.dataPath + "/Editor");

​ 注意:需要我们自己将创建
​ 作用:编辑器文件夹

  1. 开发 Unity 编辑器时,编辑器相关脚本放在该文件夹中
  2. 该文件夹中内容不会被打包出去

(七)默认资源文件夹 Standard Assets

​ 路径获取:一般不获取

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

二、同步加载资源

​ Resources 资源动态加载的作用:

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

(一)常用资源类型

  1. 预设体对象——GameObject

  2. 音效文件——AudioClip

  3. 文本文件——TextAsset

  4. 图片文件——Texture

  5. 其它类型——需要什么用什么类型

​ 注意:预设体对象加载需要实例化,其它资源加载一般直接用

(二)资源同步加载——普通方法

​ 在一个工程当中 Resources 文件夹,可以有多个 通过 API 加载时,它会自己去这些同名的 Resources 文件夹中去找资源
​ 打包时 Resources 文件夹 里的内容 都会打包在一起

  1. 加载预设体

// 1.预设体对象 想要创建在场景上 记住实例化
// 第一步:要去加载预设体的资源文件(本质上 就是加载 配置数据 在内存中)
Object obj = Resources.Load("Cube");
// 第二步:如果想要在场景上 创建预设体 一定是加载配置文件过后 然后实例化
Instantiate(obj);

// 第一步:要去加载预设体的资源文件(本质上 就是加载 配置数据 在内存中)
Object obj2 = Resources.Load("Sphere");
// 第二步:如果想要在场景上 创建预设体 一定是加载配置文件过后 然后实例化
Instantiate(obj2);

2.加载音效资源

public AudioSource audioS;

// 2.音效资源
// 第一步:就是加载数据
Object obj3 = Resources.Load("Music/BKMusic");
// 第二步:使用数据 我们不需要实例化 音效切片 我们只需要把数据 赋值到正确的脚本上即可
audioS.clip = obj3 as AudioClip;
audioS.Play();

3.加载文本资源

// 3.文本资源
// 文本资源支持的格式
// .txt
// .xml
// .bytes
// .json
// .html
// .csv
// .....
TextAsset ta = Resources.Load("Txt/Test") as TextAsset;

// 文本内容
print(ta.text);

// 字节数据组
print(ta.bytes);

4.加载图片

// 4.图片
tex = Resources.Load("Tex/TestJPG") as Texture;

(三)资源同名的解决方法

​ Resources.Load 加载同名资源时,无法准确加载出你想要的内容

private Texture tex;

// 可以使用另外的API
// 6-1加载指定类型的资源
tex = Resources.Load("Tex/TestJPG", typeof(Texture)) as Texture;

ta = Resources.Load("Tex/TestJPG", typeof(TextAsset)) as TextAsset;
print(ta.text);

// 6-2加载指定名字的所有资源
Object[] objs = Resources.LoadAll("Tex/TestJPG");
foreach (Object item in objs) {
    if (item is Texture) { ... }
    else if (item is TextAsset) { ... }
}

(四)资源同步加载——泛型方法

TextAsset ta2 = Resources.Load<TextAsset>("Tex/TestJPG");
print(ta2.text);

tex = Resources.Load<Texture>("Tex/TestJPG");

(五)总结

​ Resources 动态加载资源的方法,让拓展性更强。相对拖曳来说,它更加一劳永逸,更加方便

​ 重要知识点:

  • 记住API
  • 记住一些特定的格式
  • 预设体加载出来一定要实例化

三、异步加载资源

​ 同步加载中,如果我们加载过大的资源可能会造成程序卡顿
​ 卡顿的原因就是,从硬盘上把数据读取到内存中是需要进行计算的
​ 越大的资源耗时越长,就会造成掉帧卡顿

​ Resources 异步加载就是内部新开一个线程进行资源加载,不会造成主线程卡顿

​ 注意:异步加载不能马上得到加载的资源,至少要等一帧

(一)事件监听实现异步加载

// 1.通过异步加载中的完成事件监听 使用加载的资源
// 这句代码 你可以理解 Unity 在内部 就会去开一个线程进行资源下载
ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");
// 马上进行一个 资源下载结束 的一个事件函数监听
rq.completed += LoadOver;
// 这个 刚刚执行了异步加载的 执行代码 资源还没有加载完毕 这样用 是不对的 
// 一定要等加载结束过后 才能使用
// rq.asset ××××××××××××

private void LoadOver(AsyncOperation rq) {
    print("加载结束");
    // asset 是资源对象 加载完毕过后 就能够得到它
    tex = (rq as ResourceRequest)?.asset as Texture;
}

(二)协程实现异步加载

// 2.通过协程 使用加载的资源
StartCoroutine(Load());

private IEnumerator Load() {
    // 迭代器函数 当遇到yield return时  就会 停止执行之后的代码
    // 然后 协程协调器 通过得到 返回的值 去判断 下一次执行后面的步骤 将会是何时
    ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");
    
    // Unity 自己知道 该返回值 意味着你在异步加载资源 
    yield return rq;
    // Unity 会自己判断 该资源是否加载完毕了 加载完毕过后 才会继续执行后面的代码

    // 判断资源是否加载结束
    while (!rq.isDone) {
        // 打印当前的 加载进度 
        // 该进度 不会特别准确 过渡也不是特别明显
        print(rq.progress);
        yield return null;
    }
    tex = rq.asset as Texture;
}

(三)总结

  1. 完成事件监听异步加载
    好处:写法简单
    坏处:只能在资源加载结束后进行处理
    “线性加载”

  2. 协程异步加载
    好处:可以在协程中处理复杂逻辑,比如同时加载多个资源,比如进度条更新
    坏处:写法稍麻烦
    “并行加载”

四、资源卸载

(一)重复加载资源

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

image-20220422012203381

(二)手动释放缓存中的资源

  1. 卸载指定资源

// Resources.UnloadAsset 方法
// 注意:
// 该方法 不能释放 GameObject对象 因为它会用于实例化对象
// 它只能用于一些 不需要实例化的内容 比如 图片 和 音效 文本等等
// 一般情况下 我们很少单独使用它
GameObject obj = Resources.Load<GameObject>("Cube");
// 即使是没有实例化的 GameObject对象也不能进行卸载
Resources.UnloadAsset(obj);

2.卸载未使用的资源

// 注意:
// 一般在过场景时和GC一起使用
Resources.UnloadUnusedAssets();
GC.Collect();

五、场景异步加载

(一)回顾——场景同步切换

SceneManager.LoadScene("Name");

​ 在切换场景时,Unity 会删除当前场景上所有对象,并且去加载下一个场景的相关信息
​ 如果当前场景,对象过多或者下一个场景对象过多,这个过程会非常的耗时会让玩家感受到卡顿

​ 所以异步切换就是来解决该问题的

(二)场景异步切换

​ 场景异步加载和资源异步加载几乎一致,有两种方式:

  1. 事件回调

// 1.通过事件回调函数 异步加载
AsyncOperation ao = SceneManager.LoadSceneAsync("Name");
// 当场景异步加载结束后 就会自动调用该事件函数 我们如果希望在加载结束后 做一些事情 那么久可以在该函数中
// 写处理逻辑
ao.completed += (a) => print("加载结束");

ao.completed += LoadOver;

private void LoadOver(AsyncOperation ao) {
    print("LoadOver");
}

2.协程

// 2.通过协程异步加载
// 需要注意的是 加载场景会把当前场景上 没有特别处理的对象 都删除了
// 所以 协程中的部分逻辑 可能是执行不了的 
// 解决思路
// 让处理场景加载的脚本依附的对象 过场景时 不被移除

// 该脚本依附的对象 过场景时 不会被 移除
DontDestroyOnLoad(gameObject);

StartCoroutine(LoadScene("Name"));

private IEnumerator LoadScene(string name) {
    // 第一步
    // 异步加载场景
    AsyncOperation ao = SceneManager.LoadSceneAsync(name);
    // Unity内部的 协程协调器 发现是异步加载类型的返回对象 那么就会等待
    // 等待异步加载结束后 才会继续执行 迭代器函数中后面的步骤
    print("异步加载过程中 打印的信息");
    // 协程的好处 是异步加载场景时 我可以在加载的同时 做一些别的逻辑
    // yield return ao;
    // 第二步
    print("异步加载结束后 打印的信息");

    // 比如 我们可以在异步加载过程中 去更新进度条
    // 第一种 就是利用 场景异步加载 的进度 去更新 但是 不是特别准确 一般也不会直接用
    // while(!ao.isDone)
    // {
    //     print(ao.progress);
    //     yield return null;
    // }

    // 离开循环后 就会认为场景加载结束
    // 可以把进度条顶满 然后 隐藏进度条

    // 第二种 就是根据你游戏的规则 自己定义 进度条变化的条件
    yield return ao;
    // 场景加载结束 更新20%进度
    // 接着去加载场景中 的其它信息
    // 比如
    // 动态加载怪物
    // 这时 进度条 再更新20%
    // 动态加载 场景模型
    // 这时 就认为 加载结束了 进度条顶满 
    // 隐藏进度条
}

 

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

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

相关文章

如何自动生成正交法测试用例?

目录 引言 正交法实验 自动生成正交用例 引言 正交法测试用例是一种高效且可靠的方法&#xff0c;能够最大限度地减少测试工作量&#xff0c;同时保证覆盖所有可能的组合情况。通过了解如何优化这些测试用例的生成过程&#xff0c;可以提高产品的质量&#xff0c;降低故障率…

机器人视觉梳理(上)

原创 | 文BFT机器人 01 机器人视觉的概念 在智能制造过程中&#xff0c;通过传统的编程来执行某一特定动作的机器人&#xff08;机械手、机械手臂、机械臂等&#xff0c;未作特殊说明时&#xff0c;不作严格区分&#xff0c;统一称为机器人&#xff09;&#xff0c;将难以满足制…

【CV大模型SAM(Segment-Anything)】如何保存分割后的对象mask?并提取mask对应的图片区域?

上一篇文章【CV大模型SAM&#xff08;Segment-Anything&#xff09;】真是太强大了&#xff0c;分割一切的SAM大模型使用方法:可通过不同的提示得到想要的分割目标中详细介绍了大模型SAM&#xff08;Segment-Anything&#xff09;的不同使用方法&#xff0c;后面有很多小伙伴给…

【JVM 监控工具】使用JConsole监控进程、线程、内存、cpu、类情况

文章目录 前言一、如何启动JConsole二、如何设置JAVA程序运行时可以被JConsolse连接分析三、JConsole如何连接远程机器的JAVA程序&#xff08;举例说明&#xff09;四、性能分析概述内存线程类VM摘要MBean 五、使用Jconsole监控某方法的性能总结 前言 Jconsole是JDK自带的监控…

网络工程师必备,华为/思科/华三交换机命令对比

本期对华为/思科/华三交换机配置命令对比,来看下他们的区别在哪里&#xff0c;这里对命令做了个汇总&#xff0c;平时对命令不熟的朋友这次可以看下。 另外我们来看下华为与H3C的命令情况&#xff0c;方便大家进行对比。 一、华为交换机基础配置命令 1、创建vlan&#xff1a; …

Unity基础1——3D数学

一、Mathf &#xff08;一&#xff09;Mathf 和 Math ​ Math 是 C# 中封装好的用于数学计算的工具类 —— 位于 System 命名空间中 ​ Mathf 是 Unity 中封装好的用于数学计算的工具结构体 —— 位于 UnityEngine 命名空间中 ​ 他们都是提供来用于进行数学相关计算的 ​…

机器学习 day18(用Tensorflow搭建一个神经网络)

之前搭建神经网络的方法 先初始化输入数据X&#xff0c;创建layer 1并计算激活值a1&#xff0c;创建layer 2并计算激活值a2&#xff0c;这是前向传播代码的显式形式。 另一种简单些的创建神经网络的方法 创建layer 1和layer 2与前一种方法相同&#xff0c;但我们不需要手动…

JUC并发编程学习笔记

1&#xff1a;回顾多线程 进程和线程是什么 进程是操作系统分配资源的最小单元&#xff0c;而线程是cpu调度的最小单元。 java默认有几个线程 2个,main线程和GC线程&#xff08;GC垃圾回收机制&#xff09; java可以开启线程么 不能 并发和并行 并发,多线程操作同一个资源,cp…

纯电驱动车辆动力总成的优化与比较研究

摘要&#xff1a; 不同动力总成拓扑结构的对比分析 前言 纯电驱动的电动汽车因为集成有大容量电池组&#xff0c;可以存储取自公共电网的电能&#xff0c;用来驱动车辆的行驶。相比于传统的混合动力汽车&#xff0c;具有更加优越的节能减排效果和潜力。因此&#xff0c;近年来…

cpp文件编译过程 makefile cmake

这里写目录标题 argc argv参数头文件编译过程静态链接&#xff0c;动态链接&#xff0c;静态库&#xff0c;动态库 -shared制作使用动态库libxxx。so冲突 静态库预处理编译汇编链接目录选项-Idir 大写Iinclude<> 与 " "-I -I- 与 -I- -I ld/objdump/objcopy 选…

内网渗透—隧道搭建Ngrok与Frp内网穿透

这里写目录标题 1. 前言1.1. 隧道技术介绍1.2. 代理技术介绍1.2.1. 正向代理1.2.2. 反向代理1.2.3. 透明代理1.2.4. 正向代理与透明代理区别 2. 内网穿透2.1. Ngrok2.1.1. 访问Ngrok2.1.2. 代理设置2.1.2.1. 开通代理2.1.2.2. 配置隧道2.1.2.3. 下载客户端 2.1.3. 配置客户端2.…

P20[6-8]编码器接口测速(软)

与外部中断编码器逻辑不同,此处编码器使用的是定时器方法 1.Encoder编码器部分: #include "stm32f10x.h" // Device header void Encoder_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCm…

吐血整理,自动化测试场景处理(多场景覆盖)+解决方案

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、添加时间等待 …

53.最大子数组和

贪心算法 时间复杂度&#xff1a;代码中只有一个循环&#xff0c;循环次数为数组的长度&#xff0c;因此时间复杂度为 O(n)&#xff0c;其中 n 是数组的长度。空间复杂度&#xff1a;代码中只使用了常数级别的额外空间&#xff0c;因此空间复杂度为 O(1)。 这段代码使用贪心算…

QT C++入门学习(2) QT Creator写一个简单的上位机控制LED

上位机和下位机的概念 上位机&#xff1a;指的是可以直接发送操作指令的计算机或者单片机&#xff0c;一般提供用户操作交互界面并向用户展示反馈数据。 典型设备&#xff1a;电脑、平板、手机、面板、触摸屏 下位机&#xff1a;指的是与机器相连接的计算机或者单片机&#…

Studio 3T 2023.5 (macOS, Linux, Windows) - MongoDB 的专业 GUI、IDE 和 客户端

Studio 3T 2023.5 (macOS, Linux, Windows) - MongoDB 的专业 GUI、IDE 和 客户端 请访问原文链接&#xff1a;https://sysin.org/blog/studio-3t-2023/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Studio 3T&#xff0c;M…

黑客松必备|Bear Necessities Hackathon Office Hours汇总

由Moonbeam和AWS Startups联合主办的Bear Necessities Hackathon黑客松启动仪式已于5月30日举行。本次黑客松将历时约1个月的时间&#xff0c;包含6个挑战&#xff0c;分别由Moonbeam基金会、Chainlink、StellaSwap、SubQuery、Biconomy提供赞助&#xff0c;总奖池超过5万美金。…

面试软件测试时,面试官最想听到的答案是什么?

问题&#xff1a;面试软件测试时&#xff0c;面试官让你测一个软件&#xff0c;比如朋友圈&#xff0c;或者让你测试你的电脑为什么打不开网页&#xff0c;而QQ可以打开之类的&#xff0c;他最想听到的答案是什么&#xff1f; 如上所述&#xff0c;在实际面试中&#xff0c;面试…

懂点测试基础就敢要17k? 面试官:最多8K,多一分都没有...

公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-25k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。看简历很多都是3年工作经验&#xff0c;但面试…

Java泛型的使用

1.什么是泛型&#xff1f; 所谓泛型&#xff0c;就是允许在定义类、接口时通过 一个标识 表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时&#xff08;例如&#xff0c;继承或实现这个接口&#xff0c;用这个类型声明变量、创建对象时&#…