赞
踩
因为AssetBundle,必须要从指定bundle中加载资源。
如果没有打包,就不能加载。
那么在开发环境中,如果每次添加或者修改资源都需要重新打包,那就很麻烦,怎么解决?
1.增量打包,且不同的功能拆分成不同AssetBundle,只需打修改的。而且是增量的形式,不需要那么长时间。
2.使用之前生成的自定义依赖关系表,读取资源名对应的资源路径,通过编辑器下的AssetDataBase.Load方法进行加载。
2 的优点:无需每次打包
2 的缺点:可能表现形式不一样,比如说一个面板在editor下加载完成了,但是在AB模式下,可能需要更长的时间进行加载。如果这中间的协议到了或者没到,就会出问题。这种逻辑一样但是表现不一样的问题,是非常坑爹的!
这里还是推荐使用 2 的方式。
那么在真机中,就需要真正的使用AB了。
需要一套加载框架,可以让使用者方便的加载资源。
并且采用全部异步加载的方式,因为Unity推出的最新Addressable资源系统,也是只提供了异步加载接口。
(同步也有,但是是过时的方法)
这里把所有的异步请求,封装的成一个异步操作的对象。
无论是加载任何资源,统一返回异步操作对象,如下图所示:
其中包括:进度、返回结果、错误信息、是否完成,以及完成时的回调。
加载的主逻辑:
解释:
1.如果资源已经加载过了,就直接返回
2.如果资源没加载过,那就开始加载。
开始加载会出现两种情况:
a.其他地方已经请求加载过了,那就直接返回这个AssetLoader异步操作对象。
b.首次加载,直接创建AssetLoader,开启协程处理其中的Load()方法,再把这个异步操作对象添加到字典中,如果其他请求获取时,直接返回。
AssetLoader,就是一个异步操作对象,负责加载资源。
包含:需要加载的资源名,包名,依赖包名,ABRequest对象。
其Load方法为:
首先通过ABManager异步加载assetBundle,加载完成后进行赋值。
再通过异步接口 LoadAssetAsync 加载资源,完成后进行SetResult()进行回调OnComplete接口。
异步操作对象的OnComplete接口,负责完成时回调给调用者,存在两种情况:
a.已加载完成,直接掉用回调。
b.未加载完成,保存到本地,等到SetResult()时,进行统一回调。
使用起来的样子:(其中OnComplete里面的lambda表达式,就是参数中的callback)
那么回到刚才,如何加载Bundle呢?
加载Bundle,需要BundleLoader和FullBundleLoader,代表单个包加载和有依赖的包加载异步对象。
通过其中的IsDone表示,次包是否加载完成。
Bundle包含:包名, 依赖的包名,以及引用计数等等。
其中的Load方法为:
很简单,通过LoadFromFileAsync进行异步加载。
完成时调用SetResult()即可。
那么如何区别依赖是否加载完成了呢?
在IsDone进行判断,如果主包和依赖的包都加载完成,这个IsDone才返回true。
然后在AssetLoader那里的,Load()才会继续往下走,加载资源。
不会出现,没有加载完依赖就加载资源,“粉色”的情况。
引用计数
assetbundle需要使用引用计数,来进行正确的释放。
加载包内资源,会把这个包的引用计数+1
卸载包内资源,会把这个包的引用计数-1
加载肯定都会通过统一接口进行加载,但是卸载就不一定了。
切换场景,或者作为子物体等方式,或者直接被Destory了,那就无法把引用计数-1了。
有的时候调用者也会忘了这异步操作。
还是那句话,好的规范好的团队固然重要,但是写工具还是要从本质上解决问题。
怎么办?
采用弱引用Weak Reference
比如:对加载出来的所有资源都构造成弱引用,每60s,对其遍历
满足这几个条件,就是资源已经无效了,就可以走释放逻辑了,找到对应的包,把引用计数-1。
当这个包的引用计数为0时,就可以通过assetBundle.Unload(true)进行释放资源了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。