接着前两篇,我们继续测试 AssetBundle 方式的资源加载(实际是 用最新的Addressable Assets方式),然后再销毁与卸载,观察对应的内存变化。
这里不讲解 AssetBundle 的基本原理了,不了解的同学可以看官方文档:
https://docs.unity3d.com/Manual/AssetBundlesIntro.html
Addressable Assets 说明文档:
先说结论:
1,不触发时,不占用什么资源
2,Addressables.LoadAssetAsync()会载入Mesh(几乎等同于 Resources.Load() )。
3,Instantiate()生成游戏体的时候,会载入对应的Texture,占用内存。
4,Addressables.ReleaseInstance() 销毁游戏体时,会马上释放小部分显存。Unity等待GC时机*(见下面注释1),再进行内存清理。
5,Resources.UnloadUnusedAssets() 可以清理内存,会把没有使用(或者资源=null)的资源清理掉。注意,官方建议在允许卡顿的情况下调用(比如loading界面),因为这是一个非常缓慢的操作。
注释1: 对于bundle(里面含有资源A/B/C),你可以部分加载(比如A),或者全部加载(ABC),但不能部分卸载。在bundle本身完全卸载之前,不会卸载任何东西.。除非你调用了Resources.UnloadUnusedAssets()。官方文档的解释:https://docs.unity3d.com/Packages/com.unity.addressables@1.8/manual/MemoryManagement.html
下面是试验过程,可以不看:
在空场景的摄像机上,挂上如下脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
/// <summary>
/// 设计编写:常成功
/// 创建时间:2020/05/09
/// 脚本功能:Addressables 测试, Instantiate()实例化后, 再卸载资源
/// 挂载位置:默认场景的摄像机上
/// </summary>
public class Test_A_Mem_2 : MonoBehaviour
{
// 记录实例化的游戏体
public List<GameObject> obj_list;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// 按下[1], 加载资源并实例化
if (Input.GetKeyDown(KeyCode.Alpha1))
{
Debug.Log("Num 1: InstantiateAsync");
Addressables.InstantiateAsync("Assets/Scenes/Test_Memery/prefabs/atc_geye@idle.prefab").Completed += OnLoadDone;
}
// 按下[2], 加载资源并实例化
if (Input.GetKeyDown(KeyCode.Alpha2))
{
Debug.Log("Num 2: InstantiateAsync");
Addressables.InstantiateAsync("Assets/Scenes/Test_Memery/prefabs/atc_niya@idle.prefab").Completed += OnLoadDone;
}
// 按下[3], 加载资源并实例化
if (Input.GetKeyDown(KeyCode.Alpha3))
{
Debug.Log("Num 3: InstantiateAsync");
Addressables.InstantiateAsync("Assets/Scenes/Test_Memery/prefabs/Car_2C 1.prefab").Completed += OnLoadDone;
}
// 按下[右键], 以游戏体为单位, 逐个释放资源
if (Input.GetMouseButtonDown(1))
{
int tail_index = obj_list.Count - 1;
// 相当于Destroy()
Addressables.ReleaseInstance(obj_list[tail_index]);
obj_list.RemoveAt(tail_index);
Debug.Log("Mouse R:" + tail_index.ToString());
}
// 按下[D], 释放已经没有引用的资源
if (Input.GetKeyDown(KeyCode.D))
{
obj_list = null;
Debug.Log("Key D:");
Resources.UnloadUnusedAssets();
}
}
// 异步加载的回调函数
private void OnLoadDone(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<GameObject> obj)
{
// In a production environment, you should add exception handling to catch scenarios such as a null result.
if (obj.Result != null)
{
obj_list.Add(obj.Result);
}
else
{
Debug.LogWarning("LoadAssetAsync Error! ");
}
}
}
1
2
3
右1
右2
右3
D