赞
踩
- // 注意 该方式 获取到的路径 一般情况下 只在 编辑模式下使用
- // 我们不会在实际发布游戏后 还使用该路径
- // 游戏发布过后 该路径就不存在了
- print(Application.dataPath);
- // 路径获取:
- // 一般不获取
- // 只能使用Resources相关API进行加载
- // 如果硬要获取 可以用工程路径拼接
- print(Application.dataPath + "/Resources");
注意:需要我们自己创建
作用:资源文件夹
需要通过 Resources 相关 API 动态加载的资源需要放在其中
该文件夹下所有文件都会被打包出去
打包时 Unity 会对其压缩加密
该文件夹打包后只读 只能通过 Resources 相关 API 加载
- // 路径获取:
- print(Application.streamingAssetsPath);
注意:需要我们自己将创建
作用:流文件夹
打包出去不会被压缩加密,可以任由我们摆布
移动平台只读,PC 平台可读可写
可以放入一些需要自定义动态加载的初始资源
- // 路径获取:
- print(Application.persistentDataPath);
注意:不需要我们自己将创建
作用:固定数据文件夹
所有平台都可读可写
一般用于放置动态下载或者动态创建的文件,游戏中创建或者获取的文件都放在其中
路径获取:一般不获取
注意:需要我们自己将创建
作用:插件文件夹
不同平台的插件相关文件放在其中,比如 IOS 和 Android 平台
- // 路径获取:
- // 一般不获取
- // 如果硬要获取 可以用工程路径拼接
- print(Application.dataPath + "/Editor");
注意:需要我们自己将创建
作用:编辑器文件夹
路径获取:一般不获取
注意:需要我们自己将创建
作用:默认资源文件夹
一般 Unity 自带资源都放在这个文件夹下,代码和资源优先被编译
Resources 资源动态加载的作用:
注意:预设体对象加载需要实例化,其它资源加载一般直接用
在一个工程当中 Resources 文件夹,可以有多个 通过 API 加载时,它会自己去这些同名的 Resources 文件夹中去找资源
打包时 Resources 文件夹 里的内容 都会打包在一起
- // 1.预设体对象 想要创建在场景上 记住实例化
- // 第一步:要去加载预设体的资源文件(本质上 就是加载 配置数据 在内存中)
- Object obj = Resources.Load("Cube");
- // 第二步:如果想要在场景上 创建预设体 一定是加载配置文件过后 然后实例化
- Instantiate(obj);
-
- // 第一步:要去加载预设体的资源文件(本质上 就是加载 配置数据 在内存中)
- Object obj2 = Resources.Load("Sphere");
- // 第二步:如果想要在场景上 创建预设体 一定是加载配置文件过后 然后实例化
- Instantiate(obj2);
- public AudioSource audioS;
-
- // 2.音效资源
- // 第一步:就是加载数据
- Object obj3 = Resources.Load("Music/BKMusic");
- // 第二步:使用数据 我们不需要实例化 音效切片 我们只需要把数据 赋值到正确的脚本上即可
- audioS.clip = obj3 as AudioClip;
- audioS.Play();
- // 3.文本资源
- // 文本资源支持的格式
- // .txt
- // .xml
- // .bytes
- // .json
- // .html
- // .csv
- // .....
- TextAsset ta = Resources.Load("Txt/Test") as TextAsset;
-
- // 文本内容
- print(ta.text);
-
- // 字节数据组
- print(ta.bytes);
- // 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 动态加载资源的方法,让拓展性更强。相对拖曳来说,它更加一劳永逸,更加方便
重要知识点:
同步加载中,如果我们加载过大的资源可能会造成程序卡顿
卡顿的原因就是,从硬盘上把数据读取到内存中是需要进行计算的
越大的资源耗时越长,就会造成掉帧卡顿
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;
- }
完成事件监听异步加载
好处:写法简单
坏处:只能在资源加载结束后进行处理
“线性加载”
协程异步加载
好处:可以在协程中处理复杂逻辑,比如同时加载多个资源,比如进度条更新
坏处:写法稍麻烦
“并行加载”
Resources 加载一次资源过后,该资源就一直存放在内存中作为缓存,第二次加载时发现缓存中存在该资源,会直接取出来进行使用
所以多次重复加载不会浪费内存,但是会浪费性能(每次加载都会去查找取出,始终伴随一些性能消耗)
- // Resources.UnloadAsset 方法
- // 注意:
- // 该方法 不能释放 GameObject对象 因为它会用于实例化对象
- // 它只能用于一些 不需要实例化的内容 比如 图片 和 音效 文本等等
- // 一般情况下 我们很少单独使用它
- GameObject obj = Resources.Load<GameObject>("Cube");
- // 即使是没有实例化的 GameObject对象也不能进行卸载
- Resources.UnloadAsset(obj);
2.卸载未使用的资源
- // 注意:
- // 一般在过场景时和GC一起使用
- Resources.UnloadUnusedAssets();
- GC.Collect();
SceneManager.LoadScene("Name");
在切换场景时,Unity 会删除当前场景上所有对象,并且去加载下一个场景的相关信息
如果当前场景,对象过多或者下一个场景对象过多,这个过程会非常的耗时会让玩家感受到卡顿
所以异步切换就是来解决该问题的
场景异步加载和资源异步加载几乎一致,有两种方式:
- // 1.通过事件回调函数 异步加载
- AsyncOperation ao = SceneManager.LoadSceneAsync("Name");
- // 当场景异步加载结束后 就会自动调用该事件函数 我们如果希望在加载结束后 做一些事情 那么久可以在该函数中
- // 写处理逻辑
- ao.completed += (a) => print("加载结束");
-
- ao.completed += LoadOver;
-
- private void LoadOver(AsyncOperation ao) {
- print("LoadOver");
- }
- // 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%
- // 动态加载 场景模型
- // 这时 就认为 加载结束了 进度条顶满
- // 隐藏进度条
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。