图解内存管理
进行本文之前请各位读者务必要对托管堆有一个清晰的认识,如果对.NET托管堆还有不清楚的地方可以查看我的上一篇文章 Profiler深挖-托管堆(9) https://connect.unity.com/p/profilershen-wa-tuo-guan-dui-9
线程栈:保存着函数的调用顺序以及参数的传递,包括局部方法体中的值类型变量都保存在线程栈中。线程栈中的值类型变量内存由系统管理,不存在垃圾回收速度非常快。比如unity中报错了,我们会在 Consloe里看调用顺序,它就是线程栈执行的顺序。
托管堆内存&非托管内存:这篇会详细的说托管堆内存和非托管内存在Unity内存管理上的应用。
1).Resource.Load
var tex = Resources.Load<Texture>("Texture");
如下图所示,var tex变量被保存在托管堆中,并且指向Texture贴图的文件内存,实际Texture的文件内存保存在非托管内存中。而 tex无论是指向多大的贴图,tex在堆内存中的大小始终是一样的。
接着将贴图赋值给RawImage
var tex = Resources.Load<Texture>("Texture"); GetComponent<RawImage>().texture = tex;
如下图所示,此时托管堆中tex和rawImage.texture的两个变量都指向了托管堆中的这个texture。
继续由于tex是方法体中的临时变量,那么方法执行结束以后,会在下一次垃圾回收时清理掉tex对象。
private void Start() { var tex = Resources.Load<Texture>("Texture"); GetComponent<RawImage>().texture = tex; }
如图tex变量已经被清理,但是此时 rawImage.texture引用这texture图片内存。
在某个时刻将RawImage对象删除,并且等到下一次垃圾回收时会清理掉rawImage.texture对象。
//... Destroy(GetComponent<RawImage>());
如下图所示,托管堆上已经没有对象在引用texture非托管内存了,但是非托管的贴图内存还在。
继续调用卸载无用资源函数
//... Resources.UnloadUnusedAssets();
如下图所示此时托管堆和非托管内存都被安全清理掉了。
资源内存加载与清理是比较简单的,我们在来看看游戏对象资源,也就是Prefab内存,Prefab是最容易出错了,这回我们用AssetBundle的流程来理解它。
2)AssetBu