我正在使用Asset Bundle浏览器顶部的一个小工具来估计一个包将占用多少RAM,以便在将一个包提交给艺术家进行版本控制之前,我可以设置一个硬性限制/验证。 / p>
我的方法是:
使用bundle.LoadAllAssets()加载捆绑包
从包中创建序列化对象
访问序列化属性“ m_PreloadTable”
遍历每个objectReferenceValue
获取它,然后使用Profiler.GetRuntimeMemorySizeLong(object)
将其添加到词典中
如果要进行测试,这里是完整的编辑器类:
[CustomEditor(typeof(LoadBundle))]
public class LoadBundleEditor: Editor
{
public string BundleName;
private AssetBundle _bundle;
private GameObject _prefab;
private Dictionary<Type, float> TotalMemory = new Dictionary<Type, float>();
List<string> PreloadedObjects = new List<string>();
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Load Bundle"))
{
LoadBundle loader = (LoadBundle)target;
EditorCoroutineUtility.StartCoroutine(LoadPrefabRequest(loader.BundleName + ".bundle"), this);
}
}
public IEnumerator LoadPrefabRequest(string bundleStr)
{
if (_bundle != null)
{
_bundle.Unload(true);
yield return null;
}
TotalMemory.Clear();
PreloadedObjects.Clear();
AssetBundle bundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, bundleStr));
bundle.LoadAllAssets();
_bundle = bundle;
yield return null;
float total = 0;
SerializedObject sBundle = new SerializedObject(bundle);
SerializedProperty allAssets = sBundle.FindProperty("m_PreloadTable");
foreach (SerializedProperty asset in allAssets)
{
if (asset.objectReferenceValue != null)
{
float size = GetAssetSize(asset, asset.objectReferenceValue.GetType());
if (PreloadedObjects.Contains(asset.objectReferenceValue.name + size))
continue;
if (TotalMemory.ContainsKey(asset.objectReferenceValue.GetType()))
{
TotalMemory[asset.objectReferenceValue.GetType()] += size;
}
else
{
TotalMemory.Add(asset.objectReferenceValue.GetType(), size);
}
PreloadedObjects.Add(asset.objectReferenceValue.name + size);
}
}
foreach (KeyValuePair<Type, float> key in TotalMemory)
{
total += key.Value;
Debug.Log(key.Key + "<color=blue> memory should be: </color>" + key.Value / 1048576f);
}
Debug.Log("<color=green> Total memory should be: </color>" + (total / 1048576f));
}
float GetAssetSize(SerializedProperty s, Type t)
{
float mem = Profiler.GetRuntimeMemorySizeLong(s.objectReferenceValue);
return mem;
}
public float GetTextureSize(SerializedProperty s)
{
float mem = Profiler.GetRuntimeMemorySizeLong((Texture2D)s.objectReferenceValue);
Debug.Log("<color=cyan> Texture size of " + s.objectReferenceValue.name + " is </color>" + mem);
return mem;
}
}
最后,我显示了每种类型的内存以及该捆绑包的总内存。
我通过在Android的一个空APK项目中加载AssetBundle并从分析器中获取“内存”快照来进行比较。然后我通过加载相同的捆绑文件将数据与“编辑器”工具进行比较(并检查编辑器内存快照以查看文件大小是否一致)。
值是不同的,在编辑器中,感觉就像是我正在加载桌面捆绑包而不是Android捆绑包。尽管资产文件是android文件,但test unity项目设置为Android。我在一些没有Android替代项的UI包中进行了测试,并且效果很好。
您是否对Unity在编辑器中加载资产捆绑的幕后行为有任何了解?
谢谢。