- Unity2021
1、测试目的
我们希望优化AB包资源缓存策略,要求有两点:
- 可以在C#测持有资源的引用,不必每次使用时都去AB包里Load
曾经做过一个简单的测试,从Dictionary缓存里取资源,比每次Load效率高几十倍(排除首次加载) - 从AB包里加载出来的资源,可以被UnloadUnused接口卸载掉
因为某些AB包的粒度较粗,所有资源都要跟着AB包一起卸载,对内存浪费还是很大的。希望资源的卸载周期跟AB包的卸载周期分离。
2、测试结论
WeakReference wr = new WeakReference(texture);
WeakReference<Texture> wr2 = new WeakReference<Texture>(texture);
2.1 对象创建的后的默认状态
- 被WeakReference持有的对象,很长时间不会被回收。
具体的极限时间没测试,这里的“长”是相对于后面的“短”来说的。
注意:这里说的是C#对象(Texture这个类的对象),不是Unity的资源(Native侧的图片二进制数据)
2.2 执行UnloadUnused之后
- 被Weak持有的Unity资源会立刻从内存卸载掉
- 短时间内,
wr.IsAlive
是true,当访问了wr.Target
后(打Log、取字段)都会将资源加载进内存!! - 长时间后,
wr.IsAlive
false同时wr.Target
是Null,这里说明C#的对象被回收了。这时候再访问wr.Target
也不会将资源加载进内存 - 下面这套操作,C#对象被回收,Unity资源留在内存:
- 执行
UnloadUnusedAssets
:此时资源从内存卸载 - 立刻访问
wr.Target
:资源被加载回内存 - 经过长时间等待(Editor里大概几十秒):C#对象被回收,Unity资源留在内存无法被访问(可以被UnloadUnused等卸载)
- 执行
2.3 执行Unload(true)之后
- Unity资源立刻从内存卸载
- 短时间内,
wr.IsAlive
是true,wr.Target
是null,访问wr.Target
也无法将资源加载进内存 - 长时间后,
wr.IsAlive
是false,wr.Target
是Null
特别说明:上面描述wr.Target
时用了【null】跟【Null】两个写法,这里时有意为之,它们都是Console打印的内容,代表了Unity对象的不同状态:
- Null:代表这个变量指向的对象是
null
,也就是没有对象 - null:代表这个变量指向的对象是有值的(如:一个Texture),但是这个对象处于一个被销毁、不可用的状态,Unity将这种状态状态的对象的name改为了
"null"
,同时ToString也是"null"
网友评论