Unity Addressables.Release()不能在析构函数中调用的问题

这两天在用Unity新出的资源管理系统 Addressable Asset System的时候发现了一个问题,Release和ReleaseInstance函数不能正确的减少资源的引用,就是ref count,经过多次实验发现,问题出在析构函数上

因为第一次用没经验,对于一些不继承Mono的类,我想当然认为要释放资源的引用应该在析构函数中,对于一般的c#非托管资源来说这没什么问题,因对资源的引用恰好就是对象的生命周期,但是Addressables内部实现好像并不是那么简单

Class Entity : MonoBehaviour {  
	AsyncOperationHandle handler;
	
	void Start(){
		handler = Addressables.LoadAssetAsync("图片");
	}
	
	~Entity(){
		Debug.log("Destructor Start");
		Addressables.Release(handler);
		Debug.log(“Destructor End");
	}
 }

// output:
// Destructor Start

如上面代码所示,切换场景的时候,物体被销毁,GC自动回收对象,可以看到析构函数执行了Destructor Start,但是没有执行Destructor End。

不知道为什么,仿佛很神奇的被Release函数“阻塞”了一样,而查看Profile发现,“图片”的Ref count = 1,资源没有被卸载,Get一个内存泄漏,Wonderful!

这里不是很懂为什么出现这种情况,也没看源码,有知道的大佬望告知。

我现在的解决办法是:如果继承MonoBehaviour的类,就在OnDestroy()中进行Release,没有继承Mono的类,实现IDisposable接口,手动调用Dispose函数进行Release,如下

Class GameManager : MonoBehaviour {
   
   AsyncOperationHandle handler;
   Entity entity;
   
   void Start(){
       handler = Addressables.InstantiateAsync("prefab");
       entity = new Entity();
       entity.handler = Addressables.LoadAssetAsync("Sprite");
   }

   void OnDestroy(){
       Addressables.ReleaseInstance(handler);
       entity.Dispose();
   }
}

Class Entity : IDispose {  
   public AsyncOperationHandle handler;
   	
   void Dispose(){
       Addressables.Release(handler);
   }
}

再查看Profile面板,发现场景切换的时候,ref count都为0,资源可以正确卸载了,这个方法解决了问题,但是需要手动管理比较麻烦,如果有更好的解决方案欢迎讨论。

你可能感兴趣的:(Unity那点Bug)