Ejemplo n.º 1
0
        private void PostProcessBuild(BuildTarget target, string path, Func <Dictionary <string, long>, Dictionary <string, long> > assetsGetter)
        {
            toolOverheadTimer.Start();

            try
            {
                EditorUtility.DisplayProgressBar("Better Build Info", "Analyzing build...", 1.0f);

                List <AssetInfo>          infos = new List <AssetInfo>();
                Dictionary <string, long> scenesSizesFromLog = new Dictionary <string, long>();

                {
                    Dictionary <string, long> assetsFromLog = assetsGetter(scenesSizesFromLog);
                    infos = GetAssetsAndSizes(assetsUsedByScenes, assetsFromLog);
                }

                BuildInfoProcessorUtils.DiscoverDependenciesAndMissingAtlases(infos, assetsUsedByScenes, detailsCollector);

                if (detailsCollector != null)
                {
                    BuildInfoProcessorUtils.FinishCollectingDetails(infos, detailsCollector);
                }

                BuildArtifactsInfo artifactsInfo = null;
                try
                {
                    artifactsInfo = BuildArtifactsInfo.Create(target, path);
                }
                catch (Exception ex)
                {
                    Log.Warning("Unable to obtain build artifacts info: {0}", ex);
                }

                BuildInfoProcessorUtils.RefreshScenesInfo(scenesSizesFromLog, infos, artifactsInfo, processedScenes, scenesDetails, detailsCollector);

                if (artifactsInfo != null)
                {
                    BuildInfoProcessorUtils.RefreshModulesInfo(infos, artifactsInfo);
                }

                // sort infos based on paths (easier diffs)
                infos.Sort(BuildInfoProcessorUtils.PathComparer);

                if (artifactsInfo != null)
                {
                    BuildInfoProcessorUtils.RefreshOtherArtifacts(infos, artifactsInfo);
                }

                if (detailsCollector != null)
                {
                    EditorUtility.DisplayProgressBar("Better Build Info", "Analyzing build... (compressed sizes)", 1.0f);
                    BuildInfoProcessorUtils.FinishCalculatingCompressedSizes(infos, detailsCollector);
                    BuildInfoProcessorUtils.CalculateScriptReferences(infos, detailsCollector);
                }

                var settings = BuildInfoProcessorUtils.GetPlayerSettings(typeof(PlayerSettings))
                               .Concat(BuildInfoProcessorUtils.GetPlayerSettings(typeof(EditorUserBuildSettings)));

#if UNITY_ANDROID
                settings = settings.Concat(BuildInfoProcessorUtils.GetPlayerSettings(typeof(PlayerSettings.Android)));
#elif UNITY_IOS
                settings = settings.Concat(BuildInfoProcessorUtils.GetPlayerSettings(typeof(PlayerSettings.iOS)));
#endif

                var buildInfo = new BuildInfo()
                {
                    dateUTC      = DateTime.UtcNow.Ticks,
                    buildTarget  = target.ToString(),
                    projectPath  = Environment.CurrentDirectory.Replace('\\', '/'),
                    outputPath   = path,
                    unityVersion = Application.unityVersion,

                    buildTime    = buildTimer.ElapsedMilliseconds / 1000.0f,
                    overheadTime = toolOverheadTimer.ElapsedMilliseconds / 1000.0f,

                    assets               = infos,
                    scenes               = processedScenes.Distinct().ToList(),
                    buildSettings        = settings.GroupBy(x => x.name).OrderBy(x => x.Key).Select(x => x.FirstOrDefault()).ToList(),
                    environmentVariables = System.Environment.GetEnvironmentVariables().Cast <DictionaryEntry>().Select(x => new BuildSetting()
                    {
                        name  = x.Key.ToString(),
                        value = x.Value.ToString()
                    }).OrderBy(x => x.name).ToList(),
                };

                if (artifactsInfo != null)
                {
                    buildInfo.totalSize             = artifactsInfo.totalSize.uncompressed;
                    buildInfo.compressedSize        = artifactsInfo.totalSize.compressed;
                    buildInfo.streamingAssetsSize   = artifactsInfo.streamingAssetsSize;
                    buildInfo.runtimeSize           = artifactsInfo.runtimeSize.uncompressed;
                    buildInfo.compressedRuntimeSize = artifactsInfo.runtimeSize.compressed;
                }
                ;

                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(BuildInfo));

                var outputPath = string.Empty;

                try
                {
                    outputPath = BuildInfoSettings.Instance.GetOutputPath(DateTime.Now, target, path);

                    var dirName = ReliablePath.GetDirectoryName(outputPath);
                    if (!string.IsNullOrEmpty(dirName) && !Directory.Exists(dirName))
                    {
                        Directory.CreateDirectory(dirName);
                    }

                    using (var writer = File.CreateText(outputPath))
                    {
                        serializer.Serialize(writer, buildInfo);
                    }

                    Log.Info("Generated report at: {0}", outputPath);

                    if (BuildInfoSettings.Instance.autoOpenReportAfterBuild)
                    {
                        BuildInfoSettings.ReportToOpen = outputPath;
                    }
                }
                catch (System.Exception ex)
                {
                    var tempPath = ReliablePath.GetTempPath() + "BBI_" + Guid.NewGuid().ToString() + ".bbi";
                    Log.Error("Error saving report at {0}, saving it temporarily at {1}. Copy it manually to a target location. Error details: {2}", outputPath, tempPath, ex);

                    using (var writer = new StreamWriter(tempPath))
                    {
                        serializer.Serialize(writer, buildInfo);
                    }
                }
            }
            catch (System.Exception ex)
            {
                Log.Error("Unexpected error: {0}", ex);
            }
            finally
            {
                if (!BuildInfoSettings.Instance.autoOpenReportAfterBuild)
                {
                    BuildInfoSettings.ReportToOpen = null;
                }

                EditorUtility.ClearProgressBar();
            }
        }
Ejemplo n.º 2
0
        private static void CollectUsedAssets(Scene scene, string sceneName, Dictionary <string, AssetInfo> assets, Dictionary <int, string> preexistingPrefabInstances, BuildInfoAssetDetailsCollector collector, out AssetProperty[] sceneDetails)
        {
            List <AssetProperty> details = new List <AssetProperty>();
            Func <string, UnityEngine.Object, AssetInfo> touchEntry = (assetPath, asset) =>
            {
                AssetInfo entry;
                if (!assets.TryGetValue(assetPath, out entry))
                {
                    entry = new AssetInfo()
                    {
                        path = assetPath,
                    };

                    assets.Add(assetPath, entry);
                }

                if (collector != null && entry.details == null)
                {
                    bool isMainAsset = true;
                    if (!AssetDatabase.IsMainAsset(asset) && !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(asset)))
                    {
                        isMainAsset = false;
                    }

                    if (isMainAsset)
                    {
                        details.Clear();

                        Log.Debug("Collecting details for asset: {0}", assetPath);
                        collector.CollectForAsset(details, asset, assetPath);
                        entry.details = details.ToArray();
                    }
                    else
                    {
                        Log.Debug("Not a main asset: {0} {1}", asset.name, AssetDatabase.GetAssetPath(asset));
                    }
                }

                if (!string.IsNullOrEmpty(sceneName))
                {
                    int sceneIndex = entry.scenes.BinarySearch(sceneName);
                    if (sceneIndex < 0)
                    {
                        entry.scenes.Insert(~sceneIndex, sceneName);
                    }
                }
                return(entry);
            };

            var legacySpriteHandler = UnityVersionAgnostic.IsUsingLegacySpriteAtlases ? BuildInfoProcessorUtils.CreateLegacyAtlasHandler(touchEntry) : null;

            // include inactive ones too
            var sceneRoots = scene.GetRootGameObjects();

            sceneDetails = null;
            if (collector != null)
            {
                Log.Debug("Collecting scene details: {0}", sceneName);
                sceneDetails = collector.CollectForCurrentScene(sceneRoots);
            }

            Log.Debug("Processing scene objects for scene: {0}", sceneName);

            IEnumerable <UnityEngine.Object> objects = EditorUtility.CollectDependencies(sceneRoots).Where(x => x);

            foreach (var obj in objects)
            {
                string assetPath;
                var    dep = obj;

                if (!EditorUtility.IsPersistent(dep))
                {
                    if (dep is GameObject)
                    {
                        // hopefully this will work some day :(
                        // if (PrefabUtility.GetPrefabInstanceStatus(dep) == PrefabInstanceStatus.Connected)
                        // {
                        //
                        //     assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(dep);
                        // }
                        if (preexistingPrefabInstances != null)
                        {
                            // well, let's see if the workaround worked
                            preexistingPrefabInstances.TryGetValue(dep.GetInstanceID(), out assetPath);
                        }
                        else
                        {
                            assetPath = null;
                        }

                        if (string.IsNullOrEmpty(assetPath))
                        {
                            continue;
                        }

                        dep = AssetDatabase.LoadAssetAtPath <GameObject>(assetPath);

                        if (dep == null)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    assetPath = AssetDatabase.GetAssetPath(dep);
                }

                if (string.IsNullOrEmpty(assetPath))
                {
                    Log.Debug(dep, "empty path: name: {0}, scene: {1}", dep.name, sceneName);
                    continue;
                }

                touchEntry(assetPath, dep);

                if (legacySpriteHandler != null && dep is UnitySprite)
                {
                    legacySpriteHandler((UnitySprite)dep, assetPath);
                }
            }

            // add lightmaps
            Log.Debug("Processing lightmaps for scene: {0}", sceneName);
            foreach (var data in UnityEngine.LightmapSettings.lightmaps)
            {
                if (data.GetDirectional())
                {
                    touchEntry(AssetDatabase.GetAssetPath(data.GetDirectional()), data.GetDirectional());
                }
                if (data.GetLight())
                {
                    touchEntry(AssetDatabase.GetAssetPath(data.GetLight()), data.GetLight());
                }
            }

            // now check lightmap settings
            var lightmapSettings = BuildInfoProcessorUtils.GetLightmapSettings();

            for (var prop = new SerializedObject(lightmapSettings).GetIterator(); prop.Next(true);)
            {
                if (prop.propertyType == SerializedPropertyType.ObjectReference)
                {
                    var obj = prop.objectReferenceValue;
                    if (obj && EditorUtility.IsPersistent(obj))
                    {
                        string path = AssetDatabase.GetAssetPath(obj);
                        touchEntry(path, obj);
                    }
                }
            }
        }