Asset Bundle Analyzer

Hi, all.
For those of you who lack the tool to get better understanding what is inside your asset bundle, I introduce “Asset Bundle Analyzer”. Tool is completely free of charge and you can integrate it in your project by simply copying this source code in your “Editor” folder. After that you can open utility window from Unity menu (Tools->Analyze Asset Bundle). Than you should select asset bundle you want to analyze in your project tab and press ‘analyze’ button. Also you can specify folder for temp files.
Utility output looks like:

1246563--53578--$AssetBundleAnalyzer.png

Here you can analyze what types of resources present in your bundle and what is the amount of storage space they occupy.
This is very useful if you want to understand why your asset bundle is so large or if you want to check that all shaders are extracted into separate asset bundle.
Also note ‘Compress’ checkbox. Let’s assume that all your bundles are compressed. So you can check this box and analyze approximate size of resource in you bundle. If you uncheck it you can analyze approximate run-time memory usage for resources in bundle.

Unsolved problems:

  • By the moment tool doesn’t analyze memory that used for components, only assets and Transform components are taken into account.
  • Platform detection of incoming asset bundle required. By the moment tool supports autodetection for android and ios by asset bundle name (if it contains ‘-android’ or ‘-ios’ in it’s name).

Special notes:

  • Resource sizes returned by the tool are just an approximation, but in practice precision for everything which is more than 1 Kb is good enough.

AssetBundleAnalyzer.cs:

using System.IO;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public class AssetBundleAnalyzer : EditorWindow {
	private struct StatData {
		public string typeName;
		public string objName;
		public int 	  size;
	}	
	
	private class StatDataComparer : IComparer<StatData> {
		Dictionary<string, int>	_typeSizeMap;
		
		public StatDataComparer(Dictionary<string, int>	typeSizeMap)
		{
			_typeSizeMap = typeSizeMap;
		}
		
		public int Compare(StatData stat1, StatData stat2)
		{
			int typeSize1 = _typeSizeMap[stat1.typeName];
			int typeSize2 = _typeSizeMap[stat2.typeName];
			
			int stringCompare = stat1.typeName.CompareTo(stat2.typeName);
	
			if 		  (typeSize1 > typeSize2) {
				return -1;
			} else if (typeSize1 < typeSize2) {
				return +1;
			} else if (stringCompare != 0) {
				return stringCompare;
			} else if (stat1.size > stat2.size) {
				return -1;
			} else if (stat1.size < stat2.size) {
				return +1;
			} else {
				return 0;
			}							
		}
	}
	
	private Vector2 scrollPosition = Vector2.zero;
	private bool 	compressed = false;	
	private string	outputPath = "";
	private string  selectedPath = "";
	private Object	analyzedObject = null;	
	private List<StatData>	statistics = new List<StatData>();
	private Dictionary<string, int >	typeSizeMap   = new Dictionary<string, int>();
	private Dictionary<string, bool>	typeStatusMap = new Dictionary<string, bool>();
	
	[MenuItem("Tools/Analyze Asset Bundle")]
	public static void ShowWindow()
	{
		EditorWindow.GetWindow(typeof(AssetBundleAnalyzer));
	}
		
	void OnGUI()
	{
		Object currentObject = null;
		string assetPath = "";
		
		if (Selection.activeObject != null) {
			assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(Selection.activeObject));
			if (assetPath.ToLower().Contains(".bytes")) {
				currentObject = Selection.activeObject;
			}
		}
		
		GUILayout.Label ("Asset bundle to analyze", EditorStyles.boldLabel);		
		if (currentObject != null) {
			FileInfo file = new FileInfo(assetPath);
			
			GUILayout.Label("   file: " + assetPath); 			
			GUILayout.Label("   size: " + file.Length/1024 + " Kb");
		} else {
			GUILayout.Label("   file: None (select in project)");
			GUILayout.Label("   size: 0 Kb");
		}			
		
		GUILayout.Label ("Settings", EditorStyles.boldLabel);		
		compressed = EditorGUILayout.Toggle ("   Compress", compressed);		
	
		EditorGUILayout.BeginHorizontal();
		{
			selectedPath = EditorGUILayout.TextField("   Output path: ", selectedPath);
			if (GUILayout.Button("select", GUILayout.Width(50))) {
				selectedPath = EditorUtility.SaveFolderPanel ("Select output directory", "", selectedPath);
			}
			
			outputPath = selectedPath + "/.analyze";
		}
		EditorGUILayout.EndHorizontal();
		
		EditorGUILayout.Space();
		if (GUILayout.Button ("analyze", GUILayout.Width (100))  currentObject != null) {
			if (outputPath.Length == 0) {
				Debug.LogError("Please select valid output path");
				return;
			}
			
			try {
				if (Directory.Exists(outputPath)) {
					Directory.Delete(outputPath, true);		
				}			
			} finally {
				Directory.CreateDirectory(outputPath);	
			}
			
			if (!Directory.Exists(outputPath)) {
				Debug.LogError("Please select valid output path");
				return;
			}
			
			// detect platform
			BuildTarget buildTarget = BuildTarget.Android;
			if (assetPath.Contains("-ios")) {
				buildTarget = BuildTarget.iPhone;
			} else if (assetPath.Contains("-android")) {
				buildTarget = BuildTarget.Android;
			} else {
				Debug.LogWarning("Original asset bundle platform not detected. Android selected as default");
			}
						
			analyzeAssetBundle(currentObject, buildTarget);			
		}
		
		if (analyzedObject != currentObject) {
			statistics.Clear();
			analyzedObject = null;			
		}
				
		if (analyzedObject != null) {
			scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
			{
				string curType = "";
				
				foreach(StatData data in statistics) {
					if (curType != data.typeName) {
						EditorGUILayout.BeginHorizontal();
						{											
							typeStatusMap[data.typeName] = EditorGUILayout.Foldout(typeStatusMap[data.typeName], data.typeName);		
							
							GUI.skin.label.alignment = TextAnchor.MiddleRight;
							GUI.skin.label.fontStyle = FontStyle.Bold;											
							
							GUILayout.Label(typeSizeMap[data.typeName]/1024 + " Kb");
							GUILayout.Space(400);
						}
						EditorGUILayout.EndHorizontal();
						
						curType = data.typeName;
					}
					
					if (typeStatusMap[data.typeName]) {
						EditorGUILayout.BeginHorizontal();
						{
							GUI.skin.label.alignment = TextAnchor.MiddleLeft;
							GUI.skin.label.fontStyle = FontStyle.Normal;											
							
							GUILayout.Label("    " + data.objName);
							
							GUI.skin.label.alignment = TextAnchor.MiddleRight;						
							GUILayout.Label(data.size/1024 + " Kb");
							
							GUILayout.Space(400);	
						}
						EditorGUILayout.EndHorizontal();
					}
				}
			}
			EditorGUILayout.EndScrollView();
		}
	}
	
	private void analyzeAssetBundle(Object obj, BuildTarget buildTarget)
	{	
		typeStatusMap.Clear();
		typeSizeMap.Clear();
		statistics.Clear();
		analyzedObject = obj;		
		
		string assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(obj));
		WWW www = new WWW("file:///" + assetPath);
		Object[]	loadedObjects = www.assetBundle.LoadAll();			
		
		foreach(Object loadedObj in loadedObjects) {
			string directory = outputPath + "/" + loadedObj.GetType().FullName + "/";
			if (!Directory.Exists(directory)) {
				Directory.CreateDirectory(directory);
			}
			
			string bundlePath = directory + loadedObj.name.Replace("/", ".") + "." + loadedObj.GetInstanceID() + ".bytes";
			BuildPipeline.BuildAssetBundle(loadedObj, null, bundlePath,									   
									       compressed ? 0 : BuildAssetBundleOptions.UncompressedAssetBundle,
									       buildTarget);	
			
			if (File.Exists(bundlePath)) {
				StatData	stat = new StatData();
				stat.objName  = loadedObj.name;
				stat.typeName = loadedObj.GetType().FullName;
				
				FileInfo	fileInfo = new FileInfo(bundlePath);
				stat.size     = (int) fileInfo.Length;
				
				statistics.Add(stat);
			}
		}
		
		www.assetBundle.Unload(true);
		www.Dispose();	
		
		// fill type size map
		foreach(StatData data in statistics) {
			if (typeSizeMap.ContainsKey(data.typeName)) {
				typeSizeMap[data.typeName] += data.size;
			} else {
				typeSizeMap.Add(data.typeName, data.size);
			}
		}				
		
		// fill type status map
		foreach(string typeName in typeSizeMap.Keys) {
			typeStatusMap.Add(typeName, false);
		}
		
		statistics.Sort(new StatDataComparer(typeSizeMap));		
	}
}

Hi naxel thanks for the script. unfortunately i am not able to selecet any asset bundles from project hierarchy. Am i missing any steps. !

I had the same problem at the start, but if you look at his comments you’ll see that he only had it set up for ios or android.

It should not take you much to adjust it to your needs. Try this:

Comment out lines #66 #68.

Then comment out the line at #123:

Debug.LogWarning("Original asset bundle platform not detected. Android selected as default");

and then insert this in the else block:

buildTarget = BuildTarget.StandaloneWindows;

and it should work for you in the editor (although there may be something else I missed, but I think that’s it).

You can then adjust based on your project’s needs.

It has certainly been a helpful tool for me.

It throws warnings about missing components and that I should use BuildAssetBundleOptions.CollectDependencies (which I am). A visual verification seems to indicate that everything is there and the warning is wrong.

Perhaps I’m missing something.

What a wonderful tool! Thanks so much for sharing!

@naxel thanks for sharing this tool!

i get the following error when trying to run the script in editor.

Assets/Editor/NewBehaviourScript.cs(98,86): error CS1525: Unexpected symbol `currentObject’

any ideas??

Sorry to necro this thread, but I fixed a couple things with the script to make it more usable.

  • I fixed the bug @artbyalex noticed (was missing &&).
  • I added a popup to choose the Build Target for users (it defaults to your currently selected one).

Enjoy!

using System.IO;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public class AssetBundleAnalyzer : EditorWindow {
    private struct StatData {
        public string typeName;
        public string objName;
        public int    size;
    } 
   
    private class StatDataComparer : IComparer<StatData> {
        Dictionary<string, int> _typeSizeMap;
       
        public StatDataComparer(Dictionary<string, int> typeSizeMap)
        {
            _typeSizeMap = typeSizeMap;
        }
       
        public int Compare(StatData stat1, StatData stat2)
        {
            int typeSize1 = _typeSizeMap[stat1.typeName];
            int typeSize2 = _typeSizeMap[stat2.typeName];
           
            int stringCompare = stat1.typeName.CompareTo(stat2.typeName);
           
            if        (typeSize1 > typeSize2) {
                return -1;
            } else if (typeSize1 < typeSize2) {
                return +1;
            } else if (stringCompare != 0) {
                return stringCompare;
            } else if (stat1.size > stat2.size) {
                return -1;
            } else if (stat1.size < stat2.size) {
                return +1;
            } else {
                return 0;
            }                         
        }
    }
   
    private Vector2 scrollPosition = Vector2.zero;
    private bool    compressed = false;
    private BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget;
    private string  outputPath = "";
    private string  selectedPath = "";
    private Object  analyzedObject = null;
    private List<StatData>  statistics = new List<StatData>();
    private Dictionary<string, int >    typeSizeMap   = new Dictionary<string, int>();
    private Dictionary<string, bool>    typeStatusMap = new Dictionary<string, bool>();
   
    [MenuItem("Tools/Analyze Asset Bundle")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(AssetBundleAnalyzer));
    }
   
    void OnGUI()
    {
        Object currentObject = null;
        string assetPath = "";
       
        if (Selection.activeObject != null) {
            assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(Selection.activeObject));
            if (assetPath.ToLower().Contains(".unity3d")) {
                currentObject = Selection.activeObject;
            }
        }
       
        GUILayout.Label ("Asset bundle to analyze", EditorStyles.boldLabel);      
        if (currentObject != null) {
            FileInfo file = new FileInfo(assetPath);
           
            GUILayout.Label("   file: " + assetPath);         
            GUILayout.Label("   size: " + file.Length/1024 + " Kb");
        } else {
            GUILayout.Label("   file: None (select in project)");
            GUILayout.Label("   size: 0 Kb");
        }         
       
        GUILayout.Label ("Settings", EditorStyles.boldLabel);     

        compressed = EditorGUILayout.Toggle ("   Compress", compressed);      
        buildTarget = (BuildTarget)EditorGUILayout.EnumPopup("   Build Target", buildTarget);
       
        EditorGUILayout.BeginHorizontal();
        {
            selectedPath = EditorGUILayout.TextField("   Output path: ", selectedPath);
            if (GUILayout.Button("select", GUILayout.Width(50))) {
                selectedPath = EditorUtility.SaveFolderPanel ("Select output directory", "", selectedPath);
            }
           
            outputPath = selectedPath + "/.analyze";
        }
        EditorGUILayout.EndHorizontal();
       
        EditorGUILayout.Space();
        if (GUILayout.Button ("analyze", GUILayout.Width (100)) && currentObject != null) {
            if (outputPath.Length == 0) {
                Debug.LogError("Please select valid output path");
                return;
            }
           
            try {
                if (Directory.Exists(outputPath)) {
                    Directory.Delete(outputPath, true);   
                }         
            } finally {
                Directory.CreateDirectory(outputPath);
            }
           
            if (!Directory.Exists(outputPath)) {
                Debug.LogError("Please select valid output path");
                return;
            }
           
            analyzeAssetBundle(currentObject, buildTarget);       
        }
       
        if (analyzedObject != currentObject) {
            statistics.Clear();
            analyzedObject = null;        
        }
       
        if (analyzedObject != null) {
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
            {
                string curType = "";
               
                foreach(StatData data in statistics) {
                    if (curType != data.typeName) {
                        EditorGUILayout.BeginHorizontal();
                        {                                         
                            typeStatusMap[data.typeName] = EditorGUILayout.Foldout(typeStatusMap[data.typeName], data.typeName);      
                           
                            GUI.skin.label.alignment = TextAnchor.MiddleRight;
                            GUI.skin.label.fontStyle = FontStyle.Bold;                                        
                           
                            GUILayout.Label(typeSizeMap[data.typeName]/1024 + " Kb");
                            GUILayout.Space(400);
                        }
                        EditorGUILayout.EndHorizontal();
                       
                        curType = data.typeName;
                    }
                   
                    if (typeStatusMap[data.typeName]) {
                        EditorGUILayout.BeginHorizontal();
                        {
                            GUI.skin.label.alignment = TextAnchor.MiddleLeft;
                            GUI.skin.label.fontStyle = FontStyle.Normal;                                          
                           
                            GUILayout.Label("    " + data.objName);
                           
                            GUI.skin.label.alignment = TextAnchor.MiddleRight;                    
                            GUILayout.Label(data.size/1024 + " Kb");
                           
                            GUILayout.Space(400); 
                        }
                        EditorGUILayout.EndHorizontal();
                    }
                }
            }
            EditorGUILayout.EndScrollView();
        }
    }
   
    private void analyzeAssetBundle(Object obj, BuildTarget buildTarget)
    { 
        typeStatusMap.Clear();
        typeSizeMap.Clear();
        statistics.Clear();
        analyzedObject = obj;     
       
        string assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(obj));
        WWW www = new WWW("file:///" + assetPath);
        Object[]    loadedObjects = www.assetBundle.LoadAll();        
       
        foreach(Object loadedObj in loadedObjects) {
            string directory = outputPath + "/" + loadedObj.GetType().FullName + "/";
            if (!Directory.Exists(directory)) {
                Directory.CreateDirectory(directory);
            }
           
            string bundlePath = directory + loadedObj.name.Replace("/", ".") + "." + loadedObj.GetInstanceID() + ".bytes";
            BuildPipeline.BuildAssetBundle(loadedObj, null, bundlePath,                                   
                                           compressed ? 0 : BuildAssetBundleOptions.UncompressedAssetBundle,
                                           buildTarget);  
           
            if (File.Exists(bundlePath)) {
                StatData    stat = new StatData();
                stat.objName  = loadedObj.name;
                stat.typeName = loadedObj.GetType().FullName;
               
                FileInfo    fileInfo = new FileInfo(bundlePath);
                stat.size     = (int) fileInfo.Length;
               
                statistics.Add(stat);
            }
        }
       
        www.assetBundle.Unload(true);
        www.Dispose();
       
        // fill type size map
        foreach(StatData data in statistics) {
            if (typeSizeMap.ContainsKey(data.typeName)) {
                typeSizeMap[data.typeName] += data.size;
            } else {
                typeSizeMap.Add(data.typeName, data.size);
            }
        }             
       
        // fill type status map
        foreach(string typeName in typeSizeMap.Keys) {
            typeStatusMap.Add(typeName, false);
        }
       
        statistics.Sort(new StatDataComparer(typeSizeMap));   
    }
}
2 Likes

I does not seem to work with Unity 5.

Ya it does not seem to work with unity 5. i have received the following error…,…

Assets/AssetBundleManager/AssetBundleAnalyzer.cs(179,53): error CS0619: UnityEngine.AssetBundle.LoadAll()' is obsolete: Method LoadAll has been deprecated. Script updater cannot update it as the loading behaviour has changed. Please use LoadAllAssets instead and check the documentation for details.’

Hello
Here’s a fix that makes it work in unity 5.5.

using System;
using System.IO;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;


public class AssetBundleAnalyzer : EditorWindow {
    private struct StatData {
        public string typeName;
        public string objName;
        public int    size;
    }

    private class StatDataComparer : IComparer<StatData> {
        Dictionary<string, int> _typeSizeMap;

        public StatDataComparer(Dictionary<string, int> typeSizeMap)
        {
            _typeSizeMap = typeSizeMap;
        }

        public int Compare(StatData stat1, StatData stat2)
        {
            int typeSize1 = _typeSizeMap[stat1.typeName];
            int typeSize2 = _typeSizeMap[stat2.typeName];

            int stringCompare = stat1.typeName.CompareTo(stat2.typeName);

            if        (typeSize1 > typeSize2) {
                return -1;
            } else if (typeSize1 < typeSize2) {
                return +1;
            } else if (stringCompare != 0) {
                return stringCompare;
            } else if (stat1.size > stat2.size) {
                return -1;
            } else if (stat1.size < stat2.size) {
                return +1;
            } else {
                return 0;
            }                      
        }
    }

    private Vector2 scrollPosition = Vector2.zero;
    private bool    compressed = false;
    private BuildTarget buildTarget;
    private string  outputPath = "";
    private string  selectedPath = "";
    private UnityEngine.Object  analyzedObject = null;
    private List<StatData>  statistics = new List<StatData>();
    private Dictionary<string, int >    typeSizeMap   = new Dictionary<string, int>();
    private Dictionary<string, bool>    typeStatusMap = new Dictionary<string, bool>();

    [MenuItem("Tools/Analyze Asset Bundle")]
    public static void ShowWindow()
    {
        AssetBundleAnalyzer AssetBundleAnalyzerEditorWindow = (AssetBundleAnalyzer) EditorWindow.GetWindow(typeof(AssetBundleAnalyzer));
        AssetBundleAnalyzerEditorWindow.buildTarget = EditorUserBuildSettings.activeBuildTarget;
    }

    void OnGUI()
    {          
        UnityEngine.Object currentObject = null;
        string assetPath = "";

        if (Selection.activeObject != null) {
            assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(Selection.activeObject));
            if (assetPath.Contains("AssetBundles") && !assetPath.Contains(".Manifest")) {
                currentObject = Selection.activeObject;
            }
        }

        GUILayout.Label ("Asset bundle to analyze", EditorStyles.boldLabel);    
        if (currentObject != null) {
            FileInfo file = new FileInfo(assetPath);

            GUILayout.Label("   file: " + assetPath);      
            GUILayout.Label("   size: " + file.Length/1024 + " Kb");
        } else {
            GUILayout.Label("   file: None (select in project)");
            GUILayout.Label("   size: 0 Kb");
        }      

        GUILayout.Label ("Settings", EditorStyles.boldLabel);  

        compressed = EditorGUILayout.Toggle ("   Compress", compressed);    
        buildTarget = (BuildTarget)EditorGUILayout.EnumPopup("   Build Target", buildTarget);

        EditorGUILayout.BeginHorizontal();
        {
            selectedPath = EditorGUILayout.TextField("   Output path: ", selectedPath);
            if (GUILayout.Button("select", GUILayout.Width(50))) {
                selectedPath = EditorUtility.SaveFolderPanel ("Select output directory", "", selectedPath);
            }

            outputPath = selectedPath + "/.analyze";
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        if (GUILayout.Button ("analyze", GUILayout.Width (100)) && currentObject != null) {
            if (outputPath.Length == 0) {
                Debug.LogError("Please select valid output path");
                return;
            }

            try {
                if (Directory.Exists(outputPath)) {
                    Directory.Delete(outputPath, true);
                }      
            } finally {
                Directory.CreateDirectory(outputPath);
            }

            if (!Directory.Exists(outputPath)) {
                Debug.LogError("Please select valid output path");
                return;
            }

            analyzeAssetBundle(currentObject, buildTarget);    
        }

        if (analyzedObject != currentObject) {
            statistics.Clear();
            analyzedObject = null;      
        }

        if (analyzedObject != null) {
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
            {
                string curType = "";

                foreach(StatData data in statistics) {
                    if (curType != data.typeName) {
                        EditorGUILayout.BeginHorizontal();
                        {                                      
                            typeStatusMap[data.typeName] = EditorGUILayout.Foldout(typeStatusMap[data.typeName], data.typeName);    

                            GUI.skin.label.alignment = TextAnchor.MiddleRight;
                            GUI.skin.label.fontStyle = FontStyle.Bold;                                      

                            GUILayout.Label(typeSizeMap[data.typeName]/1024 + " Kb");
                            GUILayout.Space(100);
                        }
                        EditorGUILayout.EndHorizontal();

                        curType = data.typeName;
                    }

                    if (typeStatusMap[data.typeName]) {
                        EditorGUILayout.BeginHorizontal();
                        {
                            GUI.skin.label.alignment = TextAnchor.MiddleLeft;
                            GUI.skin.label.fontStyle = FontStyle.Normal;                                        

                            GUILayout.Label("    " + data.objName);

                            GUI.skin.label.alignment = TextAnchor.MiddleRight;                  
                            GUILayout.Label(data.size/1024 + " Kb");

                            GUILayout.Space(100);
                        }
                        EditorGUILayout.EndHorizontal();
                    }
                }
            }
            EditorGUILayout.EndScrollView();
        }
    }

    private void analyzeAssetBundle(UnityEngine.Object obj, BuildTarget buildTarget)
    {
        typeStatusMap.Clear();
        typeSizeMap.Clear();
        statistics.Clear();
        analyzedObject = obj;  

        string assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(obj));
        WWW www = new WWW("file:///" + assetPath);
        UnityEngine.Object[]    loadedObjects = www.assetBundle.LoadAllAssets();      

        foreach(UnityEngine.Object loadedObj in loadedObjects) {
            string directory = outputPath + "/" + loadedObj.GetType().FullName + "/";
            if (!Directory.Exists(directory)) {
                Directory.CreateDirectory(directory);
            }

            string bundlePath = directory + loadedObj.name.Replace("/", ".") + "." + loadedObj.GetInstanceID() + ".bytes";
            try{
                BuildPipeline.BuildAssetBundle(loadedObj, null, bundlePath,                                
                    compressed ? 0 : BuildAssetBundleOptions.UncompressedAssetBundle,
                    buildTarget);
            } catch (Exception e) {
            }

            if (File.Exists(bundlePath)) {
                StatData    stat = new StatData();
                stat.objName  = loadedObj.name;
                stat.typeName = loadedObj.GetType().FullName;

                FileInfo    fileInfo = new FileInfo(bundlePath);
                stat.size     = (int) fileInfo.Length;

                statistics.Add(stat);
            }
        }

        www.assetBundle.Unload(true);
        www.Dispose();

        // fill type size map
        foreach(StatData data in statistics) {
            if (typeSizeMap.ContainsKey(data.typeName)) {
                typeSizeMap[data.typeName] += data.size;
            } else {
                typeSizeMap.Add(data.typeName, data.size);
            }
        }          

        // fill type status map
        foreach(string typeName in typeSizeMap.Keys) {
            typeStatusMap.Add(typeName, false);
        }

        statistics.Sort(new StatDataComparer(typeSizeMap));
    }
}

Still not perfect though: it’s very slow and has difficulties with dependencies.
Personally after I tried many things, I finally ended up using this asset extractor tool, which lets you inspect the bundle contents and is very fast:
https://7daystodie.com/forums/showthread.php?22675-Unity-Assets-Bundle-Extractor

1 Like

Pardon for bumping. Just adding useful info to internet traveller.
Since this thread appear very early on google search asset bundle size analyze

Hey, just to remind everyone that when building an asset bundle, editor will produce editor log file similar to when building a standalone player. You can watch size composition there too. No special tool. No magic. No 200-lines script is needed.


Scroll down to bottom for most recent messages.

For third party asset bundle, if you want to sneak peek them, probably require third party tool.
FYI: I’m using this to build my bundles. GitHub - Unity-Technologies/AssetBundles-Browser: Editor tool for viewing and debugging asset bundle contents before and after builds

PS. Just landed here from google-sensei search too. Tried the script, realized it did not work. And just realize this method.

1 Like

Thank you, very helpful!

My experience has been that these logs are no longer available. Is there an option to re-enable them?

  • As to my knowledge, these editor log cannot be turned off, (It is always output) it is part of editor core function.

  • Be noted that asset bundle system will NOT rebuild asset bundle if it is up to date, thus no log output even if you command them to build. Try remove the output files and start build fresh.

  • Or check the location of editor log file manually. Mine is at C:\Users\{USERNAME}\AppData\Local\Unity\Editor

  • Or maybe try close editor, delete log files, and start again to see if it is happily outputting the log?