找回密码
 立即注册
查看: 844|回复: 7

unity中从Resources下读取较大的资源会卡,有解决办法么?

[复制链接]
发表于 2021-3-18 17:51 | 显示全部楼层 |阅读模式
有没有类似AssetBundle的LoadAsync类似方法。也不能在其他Thread里执行unity语句,会把其他的所有脚本都卡住了。
发表于 2021-3-18 17:55 | 显示全部楼层
换成异步加载效果也很有限,因为后台loading结束之后有些操作还是必须在主线程上完成,这部分操作Profiler上面会显示为Integrate Assets in Background,对象比较复杂或者在低端机型上还是会卡很长时间。

如果是场景比较复杂考虑利用Unity的多场景编辑拆分成多个场景流式加载。如果是比较复杂的Prefab最好拆分一下,然后用脚本延时组装起来。模型和图片比较大的话在低端机型上也可能比较卡,可以考虑根据机型选择不同精度的素材。

同时也要考虑脚本的因素,如果加载的场景或者Prefab上有比较耗时的脚本,最好优化一下,Awake,OnEnable和Start都是在主线程上执行的。

另外官方也不推荐再用Resources保存资源了,Resources下面的资源要在程序启动时建立索引,复杂度是线性的,scalability不是很好,素材多了会卡,而且也不方便patch,也就比较适合放一些配置文件。正经搞最好都换成AssetBundle,如果要随app一起分发,可以把AssetBundle放到Streaming Assets里面用。如果要随app一起分发还要能更新的话,可以游戏启动的时候花点时间把AssetBundle从Streaming Assets里面导到Cache里面,性能会好很多。
发表于 2021-3-18 17:58 | 显示全部楼层
1,提前加载,在合适的时机,比如Loading界面时。

2,可以试试携程,不过很大的话估计不解决问题。
发表于 2021-3-18 18:04 | 显示全部楼层
就是到了2020年,加载仍然是unity的硬伤,也可能是大多数引擎的硬伤吧.因为要保证稳定性,所以限制了不能在子线程中执行这些过程.即使是LoadAsync异步加载,也只是从硬盘中读到内存时是异步的.其他的仍然是同步的.
我也针对这个问题去仔细看过profiler,LoadAsync或者Load实际上并不是消耗时间最多的过程,Instantiate才是消耗大户.实例化会调用预设中所有的Awake和Start(可能不太准确,对于未启用的物体,可能没有调用这两个或者只调用了一个,其实无所谓了,我也不关心.我也几乎不写这两个函数.)如果是自己写的Awake和Start还好说.但是要命的是内置组件的Awake和Start,尤其是粒子系统.这才是消耗时间最多的部分.而且最重要的是实例化是无法异步执行的.即使使用了await和async,那也只是将这个过程延后到了下一次的FixedUpdate,仍然是一帧就会执行完毕.
真的要搞定这个,一般也都是用一些歪门邪道的办法.比如分块加载,延迟加载,预加载.不过实际上都只是杯水车薪.目前我也没有找到一个比较好的办法来处理这种加载时的卡顿.
所以有时候我也会感叹,这种大型商业引擎在某些方面实际上还不如自己写的引擎.自己写的好歹还是完美支持多线程异步加载,但是商业引擎却因为兼容性和稳定性而牺牲了诸多功能 .
多线程仍然是unity最遗憾的地方.限制太多了.
至于协程,那种东西实际上在我看来除了代码结构跟普通代码不一样以外,没有实质性的区别,都是在主线程执行的而已.
发表于 2021-3-18 18:07 | 显示全部楼层
Unity - Scripting API: Resources.LoadAsync
最近几个版本才出的API。
个人没用过不过应该和AssetBundle那个版本差不多。
发表于 2021-3-18 18:15 | 显示全部楼层
这个问题我最近也比较关注,推荐一篇博文:Unity3D占用内存太大的解决方法
里面有答案。关键点在于:
全面理解Unity加载和内存管理机制之二:进一步深入和细节
Unity几种动态加载Prefab方式的差异:
其实存在3种加载prefab的方式:
一是静态引用,建一个public的变量,在Inspector里把prefab拉上去,用的时候instantiate
二是Resource.Load,Load以后instantiate
三是AssetBundle.Load,Load以后instantiate
三种方式有细节差异,前两种方式,引用对象texture是在instantiate时加载,而assetBundle.Load会把perfab的全部 assets都加载,instantiate时只是生成Clone。所以前两种方式,除非你提前加载相关引用对象,否则第一次instantiate时会 包含加载引用类assets的操作,导致第一次加载的lag。
更新:
官方论坛有人说Resources.Load和静态引用是会把所有资源都预先加载的,反复测试的结果,静态引用和Resources.Load也是OnDemand的,用到时才会加载。--------------来自上面的博文 通过 @付洋 的指正:这句话只在EDITOR模式下正确. 真机测试Resources.Load确实会预加载依赖项。
发表于 2021-3-18 18:16 | 显示全部楼层
1.一些场景中必然会出现的静态资源资源,例如山水,建筑等,预先就部署在场景(Scene)中,以场景为单位进行加载(Scene1,Scene2等)
2.会根据玩家属性有所变化的动态资源,可以考虑按需加载,比如只加载玩家视界范围内的资源,或者将地图划分为多块,按照玩家的进度加载,具体实施的时候根据游戏的业务决定策略。
3.使用LoadAsync本质上并不能很好的解决加载卡顿的问题,但是肯定能有所缓解,能一定程度上降低损失的帧率,但整体上对玩家的体验未必会更好,所以要看情况使用。
4.预先加载,在loading过程中(如果有的话)预先将一些资源进行init,可以结合第3条进行使用,如果没有场景loading这一环节,则建议加上
发表于 2021-3-18 18:24 | 显示全部楼层
拆分好资源。先加载进入场景玩家先能看到的资源。其它资源按照已后的触发条件加载
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-20 17:55 , Processed in 0.091157 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表