- Home /
Estimate Assetbundle memory Size
I'm working on a small tool on top of the Asset bundle browser to estimate how much size in RAM a bundle will take so I can put a hard limit / validation before a bundle is submitted to version control by artists.
My approach is to:
Load a bundle using bundle.LoadAllAssets()
Make a serialized object from bundle
Access the serialized property "m_PreloadTable"
loop through every objectReferenceValue
Get it Type then size using Profiler.GetRuntimeMemorySizeLong(object)
Adding that to a Dictionnary
Here is the full Editor Class if you want to do Tests:
[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;
}
}
In the end I show the memory of each Type as well as the Total Memory of that bundle.
I do a comparison by loading an AssetBundle in an empty scene project in Android and taking a Memory snapshot from the profiler. then I compare that data with my Editor tool by loading the same bundle (and also checking an editor memory snapshot to see file sizes).
And the values are different, In the Editor it feels like if i'm loading a Desktop bundle and not an Android one. Although the asset files are android ones, and the test project project is set to Android.
Do you have any idea how Unity behaves under the hood concerning assetbundles loading in the editor ?
Thanks.