using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor.AddressableAssets.Settings; using UnityEditor.SceneManagement; using UnityEngine; // !!!! this needs to be in a folder with an Assembly Defintion Reference file, // which refers to Addressables.Editor // After that it should be accessible from the Addressables > Analyze window namespace UnityEditor.AddressableAssets.Build.AnalyzeRules { class EstimateFileSizeRule : BundleRuleBase { public override bool CanFix { get { return false; } } public override string ruleName { get { return "Bundle Layout Preview Estimate Filesize"; } } public override List RefreshAnalysis(AddressableAssetSettings settings) { ClearAnalysis(); if (!BuildUtility.CheckModifiedScenesAndAskToSave()) { Debug.LogError("Cannot run Analyze with unsaved scenes"); m_Results.Add(new AnalyzeResult { resultName = ruleName + "Cannot run Analyze with unsaved scenes" }); return m_Results; } Dictionary bundleSize = new Dictionary(); Dictionary> bundleEntries = new Dictionary>(); CalculateInputDefinitions(settings); var context = GetBuildContext(settings); RefreshBuild(context); ConvertBundleNamesToGroupNames(context); // get explicot fo;es foreach (var bundleBuild in m_AllBundleInputDefs) { string bundleName = bundleBuild.assetBundleName; var sortedAssets = bundleBuild.assetNames.OrderByDescending(a => GetFileSize(a)).Distinct(); foreach (var assetPath in sortedAssets) { var filesize = GetFileSize(assetPath); bundleSize.TryGetValue(bundleName, out var currentCount); bundleSize[bundleName] = currentCount + filesize; if (!bundleEntries.ContainsKey(bundleName)) bundleEntries[bundleName] =bundleEntries[bundleName] = new List(); bundleEntries[bundleName].Add("Explicit" + kDelimiter + " " + PrintFileSize(filesize) + " " + assetPath); } } // get implicit files if (m_ExtractData.WriteData != null) { foreach (var fileToBundle in m_ExtractData.WriteData.FileToBundle) { var assetPaths = GetImplicitGuidsForBundle(fileToBundle.Key).Select(g => AssetDatabase.GUIDToAssetPath(g)); var sortedAssets = assetPaths.OrderByDescending(a => GetFileSize(a)).Distinct(); foreach (var assetPath in sortedAssets) { string bundleName = fileToBundle.Value; var filesize = GetFileSize(assetPath); bundleSize.TryGetValue(bundleName, out var currentCount); bundleSize[bundleName] = currentCount + filesize; if (AddressableAssetUtility.IsPathValidForEntry(assetPath)) { if (!bundleEntries.ContainsKey(bundleName)) bundleEntries[bundleName] =bundleEntries[bundleName] = new List(); bundleEntries[bundleName].Add("Implicit" + kDelimiter + " " + PrintFileSize(filesize) + " " + assetPath); } } } } // add main entries var bundles = bundleSize.Keys.ToList().OrderByDescending(k => bundleSize[k]); foreach (var bundle in bundles) { var bundleprefix = $"{PrintFileSize(bundleSize[bundle])} - {bundle}" ; if (!bundleEntries.ContainsKey(bundle)) { m_Results.Add(new AnalyzeResult {resultName = $"{bundleprefix} {kDelimiter} NO ASSETS ???"}); continue; } foreach (var entry in bundleEntries[bundle]) { m_Results.Add(new AnalyzeResult {resultName = $"{bundleprefix} {kDelimiter} {entry}"}); } } if (m_Results.Count == 0) m_Results.Add(noErrors); return m_Results; } [InitializeOnLoad] class RegisterEstimateFileSizeRule { static RegisterEstimateFileSizeRule() { AnalyzeSystem.RegisterNewRule(); } } private long GetFileSize(string assetPath) { if (!File.Exists(assetPath)) return -1; System.IO.FileInfo fileInfo = new System.IO.FileInfo(assetPath); return fileInfo.Length; } private string PrintFileSize(long val) { return Mathf.Round(val / 1024f / 1024f).ToString() + " MB"; } } }