上回說到,Unity專門提供了Addressables.Instantiate接口。看起來,加載與實例化應該是兩個不同的操作,搞成一個接口是不是不科學?其實,提供這個接口,也是為了大家使用的便捷。原因如下:
根據官方論壇的帖子中官方人員的解釋,Unity內部使用引用計數來進行資源管理。
1.新加載出來的資源,其引用計數為1。
2.調用一次釋放接口,則引用計數減1。引用計數為0的資源將會被釋放。
void Addressables.ReleaseAsset<TObject>(TObject asset); //釋放資源的接口
3.通過 Addressables.Instantiate 實例化出來的對象,Unity內部會記錄該對象是通過哪個資源實例化而來的。應該使用
void Addressables.ReleaseInstance(Object instance, float delay = 0);
來釋放之。實際上,每調用一次Addressables.Instantiate方法,會將該Asset的引用計數加一;而Addressables.ReleaseInstance會減少這個引用計數。如果你使用Object.Destroy釋放了它,則原始資源會一直存在於內存中。
4.對並非使用 Addresables.Instantiate 方法實例化出來的對象,例如先通過 Addressables.LoadAsset 加載得到prefab,然后拿這個prefab實例化出來的對象,以及其他途徑得到的對象,Unity內部不會記錄實例化它們的原型是哪個資源。但是你也可以調用 Addressables.ReleaseInstance 方法來釋放它們;Unity將只是單純地將它們釋放掉,而不去做引用計數相關的操作。實際上,Unity官方人員建議,對任何對象都使用這個方法來釋放之,因為你可能無法確定它的實例化方式究竟是怎樣的。這里說點題外話,既然Unity官方覺得Addressables.ReleaseInstance的行為更合理,為什么不直接將Object.Destroy方法替換掉呢?
5.任何通過Addresables.Instantiate 方法實例化出來的對象,在切換場景的時候,如果沒有標記為 DontDestroyOnLoad ,則會被自動調用Addressables.ReleaseInstance來釋放掉。
引用計數是一個很難受的東西,如果用戶在使用中始終要考慮引用計數的問題,無疑會加重思維負擔。它應該是一個內部細節問題,而用戶應該始終感覺不到它才好。不知道以后Unity會不會統一實例化和釋放的接口行為,例如在調用常規Instantiate方法時也增加引用計數,調用 Object.Destroy方法也減少之,真正隱藏掉引用計數的細節問題。