bool LoadCachedData(string path, out AssetLoadInfo assetInfo, out BuildUsageTagSet buildUsage, BuildUsageTagGlobal globalUsage) { assetInfo = default; buildUsage = default; if (!m_Parameters.UseCache || m_Cache == null) { return(false); } CacheEntry entry = GetCacheEntry(path, globalUsage); m_Cache.LoadCachedData(new List <CacheEntry> { entry }, out IList <CachedInfo> cachedInfos); var cachedInfo = cachedInfos[0]; if (cachedInfo != null) { assetInfo = (AssetLoadInfo)cachedInfo.Data[0]; buildUsage = (BuildUsageTagSet)cachedInfo.Data[1]; var objectTypes = (List <KeyValuePair <ObjectIdentifier, Type[]> >)cachedInfo.Data[2]; BuildCacheUtility.SetTypeForObjects(objectTypes); } else { GatherAssetData(path, out assetInfo, out buildUsage, globalUsage); cachedInfo = GetCachedInfo(entry, assetInfo, buildUsage); m_Cache.SaveCachedData(new List <CachedInfo> { cachedInfo }); } return(true); }
public void Setup() { BuildCacheUtility.ClearCacheHashes(); PurgeBuildCache(); RecreateBuildCache(); SetupDerived(); }
#pragma warning restore 649 /// <inheritdoc /> public ReturnCode Run() { if (m_Parameters.ScriptInfo != null) { BuildCacheUtility.SetTypeDB(m_Parameters.ScriptInfo); return(ReturnCode.SuccessNotRun); } // We need to ensure the directory is empty so prior results or other artifacts in this directory do not influence the build result if (Directory.Exists(m_Parameters.ScriptOutputFolder)) { Directory.Delete(m_Parameters.ScriptOutputFolder, true); Directory.CreateDirectory(m_Parameters.ScriptOutputFolder); } m_Results.ScriptResults = PlayerBuildInterface.CompilePlayerScripts(m_Parameters.GetScriptCompilationSettings(), m_Parameters.ScriptOutputFolder); m_Parameters.ScriptInfo = m_Results.ScriptResults.typeDB; BuildCacheUtility.SetTypeDB(m_Parameters.ScriptInfo); if (m_Results.ScriptResults.assemblies.IsNullOrEmpty() && m_Results.ScriptResults.typeDB == null) { return(ReturnCode.Error); } return(ReturnCode.Success); }
/// <inheritdoc /> public Hash128 GetHash128(IBuildLogger log) { #if UNITY_2019_3_OR_NEWER CacheEntry entry = BuildCacheUtility.GetCacheEntry(Scene); #else CacheEntry entry = BuildCacheUtility.GetCacheEntry(ProcessedScene); #endif HashSet <CacheEntry> hashObjects = new HashSet <CacheEntry>(); using (log.ScopedStep(LogLevel.Verbose, $"Gather Objects", Command.fileName)) Command.GatherSerializedObjectCacheEntries(hashObjects); List <Hash128> hashes = new List <Hash128>(); using (log.ScopedStep(LogLevel.Verbose, $"Hashing Command", Command.fileName)) hashes.Add(Command.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing UsageSet", Command.fileName)) hashes.Add(UsageSet.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing ReferenceMap", Command.fileName)) hashes.Add(ReferenceMap.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing PreloadInfo", Command.fileName)) hashes.Add(PreloadInfo.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing Info", Command.fileName)) hashes.Add(Info.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing Objects", Command.fileName)) hashes.Add(HashingMethods.Calculate(hashObjects).ToHash128()); hashes.Add(new Hash128(0, 0, 0, (uint)QualitySettingsApi.GetNumberOfLODsStripped())); hashes.Add(DependencyHash); return(HashingMethods.Calculate(hashes, Scene, entry).ToHash128()); }
/// <inheritdoc /> public Hash128 GetHash128(IBuildLogger log) { HashSet <CacheEntry> hashObjects = new HashSet <CacheEntry>(); using (log.ScopedStep(LogLevel.Verbose, $"Gather Objects {GetType().Name}", Command.fileName)) { if (Command.serializeObjects != null) { foreach (var serializeObject in Command.serializeObjects) { hashObjects.Add(BuildCacheUtility.GetCacheEntry(serializeObject.serializationObject)); } } } List <Hash128> hashes = new List <Hash128>(); using (log.ScopedStep(LogLevel.Verbose, $"Hashing Command", Command.fileName)) hashes.Add(Command.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing UsageSet", Command.fileName)) hashes.Add(UsageSet.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing ReferenceMap", Command.fileName)) hashes.Add(ReferenceMap.GetHash128()); using (log.ScopedStep(LogLevel.Verbose, $"Hashing Objects", Command.fileName)) hashes.Add(HashingMethods.Calculate(hashObjects).ToHash128()); hashes.Add(DependencyHash); return(HashingMethods.Calculate(hashes).ToHash128()); }
/// <inheritdoc /> public ReturnCode Run() { TaskInput input = new TaskInput(); input.Target = m_Parameters.Target; input.TypeDB = m_Parameters.ScriptInfo; input.BuildCache = m_Parameters.UseCache ? m_Cache : null; #if NONRECURSIVE_DEPENDENCY_DATA input.NonRecursiveDependencies = m_Parameters.NonRecursiveDependencies; #else input.NonRecursiveDependencies = false; #endif input.Assets = m_Content.Assets; input.ProgressTracker = m_Tracker; input.DependencyUsageCache = m_DependencyData.DependencyUsageCache; input.GlobalUsage = m_DependencyData.GlobalUsage; input.Logger = m_Log; foreach (SceneDependencyInfo sceneInfo in m_DependencyData.SceneInfo.Values) { input.GlobalUsage |= sceneInfo.globalUsage; } ReturnCode code = RunInternal(input, out TaskOutput output); if (code == ReturnCode.Success) { foreach (AssetOutput o in output.AssetResults) { m_DependencyData.AssetInfo.Add(o.asset, o.assetInfo); m_DependencyData.AssetUsage.Add(o.asset, o.usageTags); if (o.spriteData != null) { if (m_SpriteData == null) { m_SpriteData = new BuildSpriteData(); } m_SpriteData.ImporterData.Add(o.asset, o.spriteData); } if (!m_Parameters.DisableVisibleSubAssetRepresentations && o.extendedData != null) { if (m_ExtendedAssetData == null) { m_ExtendedAssetData = new BuildExtendedAssetData(); } m_ExtendedAssetData.ExtendedData.Add(o.asset, o.extendedData); } if (o.objectTypes != null) { BuildCacheUtility.SetTypeForObjects(o.objectTypes); } } } return(code); }
public static void GatherSerializedObjectCacheEntries(this WriteCommand command, HashSet <CacheEntry> cacheEntries) { if (command.serializeObjects != null) { var objectIds = command.serializeObjects.Select(x => x.serializationObject); var types = BuildCacheUtility.GetSortedUniqueTypesForObjects(objectIds); cacheEntries.UnionWith(types.Select(BuildCacheUtility.GetCacheEntry)); cacheEntries.UnionWith(objectIds.Select(BuildCacheUtility.GetCacheEntry)); } }
protected virtual void RecreateBuildCache() { BuildCacheUtility.ClearCacheHashes(); if (m_Cache != null) { m_Cache.Dispose(); m_Cache = null; } m_Cache = new BuildCache(); }
protected override void RecreateBuildCache() { // purge the local cache to make sure we don't load anything out of it again. // these tests need to pull from the cache server BuildCacheUtility.ClearCacheHashes(); if (m_Cache != null) { m_Cache.Dispose(); } PurgeBuildCache(); m_Cache = new BuildCache("localhost", LocalCacheServer.instance.m_port); }
internal static List <ObjectIdentifier> GetSortedSceneObjectIdentifiers(List <ObjectIdentifier> objects) { var types = new List <Type>(BuildCacheUtility.GetMainTypeForObjects(objects)); var sortedObjects = new List <SortObject>(); for (int i = 0; i < objects.Count; i++) { sortedObjects.Add(new SortObject { sortIndex = GetSortIndex(types[i]), objectId = objects[i] }); } return(sortedObjects.OrderBy(x => x.sortIndex).Select(x => x.objectId).ToList()); }
public void BuildCacheUtility_GetSortedUniqueTypesForObjects_ReturnsUniqueAndSortedTypeArray() { var includes = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(k_TempGuid, EditorUserBuildSettings.activeBuildTarget); // Test prefab is created using 2 primitive cubes, one parented to the other, so the includes will in turn contain the sequence 2x: Type[] expectedTypes = new[] { typeof(GameObject), typeof(Transform), typeof(MeshFilter), typeof(MeshRenderer), typeof(BoxCollider) }; Array.Sort(expectedTypes, (x, y) => x.AssemblyQualifiedName.CompareTo(y.AssemblyQualifiedName)); var actualTypes = BuildCacheUtility.GetSortedUniqueTypesForObjects(includes); Assert.AreEqual(expectedTypes.Length * 2, includes.Length); Assert.AreEqual(expectedTypes.Length, actualTypes.Length); CollectionAssert.AreEqual(expectedTypes, actualTypes); }
/// <inheritdoc /> public Hash128 GetHash128() { HashSet <CacheEntry> hashObjects = new HashSet <CacheEntry>(); if (Command.serializeObjects != null) { foreach (var serializeObject in Command.serializeObjects) { hashObjects.Add(BuildCacheUtility.GetCacheEntry(serializeObject.serializationObject)); } } return(HashingMethods.Calculate(Command, UsageSet.GetHash128(), ReferenceMap.GetHash128(), Info, hashObjects).ToHash128()); }
#pragma warning restore 649 /// <inheritdoc /> public ReturnCode Run() { if (m_Parameters.ScriptInfo != null) { BuildCacheUtility.SetTypeDB(m_Parameters.ScriptInfo); return(ReturnCode.SuccessNotRun); } m_Results.ScriptResults = PlayerBuildInterface.CompilePlayerScripts(m_Parameters.GetScriptCompilationSettings(), m_Parameters.ScriptOutputFolder); m_Parameters.ScriptInfo = m_Results.ScriptResults.typeDB; BuildCacheUtility.SetTypeDB(m_Parameters.ScriptInfo); if (m_Results.ScriptResults.assemblies.IsNullOrEmpty() && m_Results.ScriptResults.typeDB == null) { return(ReturnCode.Error); } return(ReturnCode.Success); }
/// <summary> /// Returns the Object Identifiers and Types in a raw Unity Serialized File. The resulting arrays will be empty if a non-serialized file path was used. /// </summary> /// <param name="path">Path to the Unity Serialized File</param> /// <param name="objectIdentifiers">Object Identifiers for all the objects in the serialized file</param> /// <param name="types">Types for all the objects in the serialized file</param> /// <param name="additionalGlobalUsage">Additional global lighting usage information to include with this custom asset</param> public void GetObjectIdentifiersAndTypesForSerializedFile(string path, out ObjectIdentifier[] objectIdentifiers, out Type[] types, BuildUsageTagGlobal additionalGlobalUsage) { // Additional global usage is local to the custom asset, so we are using a local copy of this additional data to avoid influencing the calcualtion // of other custom assets. Additionally we store all the addtional global usage for later copying back into the dependency data result for the final write build task. var globalUsage = m_GlobalUsage | additionalGlobalUsage; m_CustomUsage = m_CustomUsage | additionalGlobalUsage; if (!LoadCachedData(path, out var assetInfo, out var buildUsage, globalUsage)) { GatherAssetData(path, out assetInfo, out buildUsage, globalUsage); } // Local cache to reuse data from this function in the next function m_AssetInfo[path] = assetInfo; m_BuildUsage[path] = buildUsage; objectIdentifiers = assetInfo.includedObjects.ToArray(); types = BuildCacheUtility.GetSortedUniqueTypesForObjects(objectIdentifiers); }
public void BuildCacheUtility_GetMainTypeForObjects_ReturnsUniqueAndSortedTypeArray() { var includes = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(k_TempGuid, EditorUserBuildSettings.activeBuildTarget); // Test prefab is created using 2 primitive cubes, one parented to the other, so the includes will in turn contain the sequence: Type[] expectedTypes = new[] { typeof(GameObject), typeof(Transform), typeof(MeshFilter), typeof(MeshRenderer), typeof(BoxCollider), typeof(GameObject), typeof(Transform), typeof(MeshFilter), typeof(MeshRenderer), typeof(BoxCollider) }; // One catch, the ordering of the expected types is based on the order of includes which is in turn ordered by the local identifier in file. // Since we are generating the prefab as part of the test, and lfids generation is random, we don't know what order they will be returned in. // So sort both expected types lists and compare exact. Array.Sort(expectedTypes, (x, y) => x.AssemblyQualifiedName.CompareTo(y.AssemblyQualifiedName)); var actualTypes = BuildCacheUtility.GetMainTypeForObjects(includes); Array.Sort(actualTypes, (x, y) => x.AssemblyQualifiedName.CompareTo(y.AssemblyQualifiedName)); Assert.AreEqual(expectedTypes.Length, includes.Length); Assert.AreEqual(expectedTypes.Length, actualTypes.Length); CollectionAssert.AreEqual(expectedTypes, actualTypes); }
/// <inheritdoc /> public Hash128 GetHash128() { var prefabHashes = AssetDatabase.GetDependencies(Scene).Where(path => path.EndsWith(".prefab")).Select(AssetDatabase.GetAssetDependencyHash); #if UNITY_2019_3_OR_NEWER CacheEntry entry = BuildCacheUtility.GetCacheEntry(Scene); #else CacheEntry entry = BuildCacheUtility.GetCacheEntry(ProcessedScene); #endif HashSet <CacheEntry> hashObjects = new HashSet <CacheEntry>(); if (Command.serializeObjects != null) { foreach (var serializeObject in Command.serializeObjects) { hashObjects.Add(BuildCacheUtility.GetCacheEntry(serializeObject.serializationObject)); } } return(HashingMethods.Calculate(Command.GetHash128(), UsageSet.GetHash128(), ReferenceMap.GetHash128(), Scene, PreloadInfo.GetHash128(), prefabHashes, entry, hashObjects).ToHash128()); }
/// <inheritdoc /> public ReturnCode Run() { HashSet <ObjectIdentifier> buildInObjects = new HashSet <ObjectIdentifier>(); foreach (AssetLoadInfo dependencyInfo in m_DependencyData.AssetInfo.Values) { buildInObjects.UnionWith(dependencyInfo.referencedObjects.Where(x => x.guid == k_BuiltInGuid)); } foreach (SceneDependencyInfo dependencyInfo in m_DependencyData.SceneInfo.Values) { buildInObjects.UnionWith(dependencyInfo.referencedObjects.Where(x => x.guid == k_BuiltInGuid)); } ObjectIdentifier[] usedSet = buildInObjects.ToArray(); Type[] usedTypes = BuildCacheUtility.GetMainTypeForObjects(usedSet); if (m_Layout == null) { m_Layout = new BundleExplictObjectLayout(); } Type shader = typeof(Shader); for (int i = 0; i < usedTypes.Length; i++) { if (usedTypes[i] != shader) { continue; } m_Layout.ExplicitObjectLocation.Add(usedSet[i], ShaderBundleName); } if (m_Layout.ExplicitObjectLocation.Count == 0) { m_Layout = null; } return(ReturnCode.Success); }
public static void ExtractCommonCacheData(IBuildCache cache, IEnumerable <ObjectIdentifier> includedObjects, IEnumerable <ObjectIdentifier> referencedObjects, HashSet <Type> uniqueTypes, List <ObjectTypes> objectTypes, HashSet <CacheEntry> dependencies) { if (includedObjects != null) { foreach (var objectId in includedObjects) { var types = BuildCacheUtility.GetSortedUniqueTypesForObject(objectId); objectTypes.Add(new ObjectTypes(objectId, types)); uniqueTypes.UnionWith(types); } } if (referencedObjects != null) { foreach (var objectId in referencedObjects) { var types = BuildCacheUtility.GetSortedUniqueTypesForObject(objectId); objectTypes.Add(new ObjectTypes(objectId, types)); uniqueTypes.UnionWith(types); dependencies.Add(cache.GetCacheEntry(objectId)); } } dependencies.UnionWith(uniqueTypes.Select(cache.GetCacheEntry)); }
internal void ClearCacheEntryMaps() { BuildCacheUtility.ClearCacheHashes(); }
/// <summary> /// Default implementation of generating Asset Bundles using the Scriptable Build Pipeline. /// </summary> /// <param name="parameters">Set of parameters used for building asset bundles.</param> /// <param name="content">Set of content and explicit asset bundle layout to build.</param> /// <param name="result">Results from building the content and explicit asset bundle layout.</param> /// <param name="taskList">Custom task list for building asset bundles.</param> /// <param name="contextObjects">Additional context objects to make available to the build.</param> /// <returns>Return code with status information about success or failure causes.</returns> public static ReturnCode BuildAssetBundles(IBundleBuildParameters parameters, IBundleBuildContent content, out IBundleBuildResults result, IList <IBuildTask> taskList, params IContextObject[] contextObjects) { // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (parameters == null) { result = null; BuildLogger.LogException(new ArgumentNullException("parameters")); return(ReturnCode.Exception); } // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (taskList.IsNullOrEmpty()) { result = null; BuildLogger.LogException(new ArgumentException("Argument cannot be null or empty.", "taskList")); return(ReturnCode.Exception); } // Don't run if there are unsaved changes if (ValidationMethods.HasDirtyScenes()) { result = null; return(ReturnCode.UnsavedChanges); } AssetDatabase.SaveAssets(); ReturnCode exitCode; result = new BundleBuildResults(); BuildCacheUtility.ClearCacheHashes(); using (var interfacesWrapper = new BuildInterfacesWrapper()) #if !CI_TESTRUNNER_PROJECT using (new SceneStateCleanup()) using (var progressTracker = new ProgressTracker()) #else using (var progressTracker = new ProgressLoggingTracker()) #endif using (var buildCache = new BuildCache(parameters.CacheServerHost, parameters.CacheServerPort)) { Directory.CreateDirectory(parameters.TempOutputFolder); BuildContext buildContext; BuildLog buildLog = null; try { buildContext = new BuildContext(contextObjects); buildContext.SetContextObject(parameters); buildContext.SetContextObject(content); buildContext.SetContextObject(result); buildContext.SetContextObject(interfacesWrapper); buildContext.SetContextObject(progressTracker); buildContext.SetContextObject(buildCache); // If IDeterministicIdentifiers was passed in with contextObjects, don't add the default if (!buildContext.ContainsContextObject(typeof(IDeterministicIdentifiers))) { buildContext.SetContextObject(new Unity5PackedIdentifiers()); } buildContext.SetContextObject(new BuildDependencyData()); buildContext.SetContextObject(new BundleWriteData()); buildContext.SetContextObject(BuildCallbacks); IBuildLogger logger; if (!buildContext.TryGetContextObject <IBuildLogger>(out logger)) { logger = buildLog = new BuildLog(); buildContext.SetContextObject(buildLog); } buildCache.SetBuildLogger(logger); } catch (Exception e) { // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code result = null; BuildLogger.LogException(e); return(ReturnCode.Exception); } exitCode = BuildTasksRunner.Validate(taskList, buildContext); if (exitCode >= ReturnCode.Success) #if SBP_PROFILER_ENABLE { exitCode = BuildTasksRunner.RunProfiled(taskList, buildContext); } #else { exitCode = BuildTasksRunner.Run(taskList, buildContext); } #endif if (Directory.Exists(parameters.TempOutputFolder)) { Directory.Delete(parameters.TempOutputFolder, true); } if (buildLog != null) { string buildLogPath = parameters.GetOutputFilePathForIdentifier("buildlogtep.json"); Directory.CreateDirectory(Path.GetDirectoryName(buildLogPath)); File.WriteAllText(parameters.GetOutputFilePathForIdentifier("buildlogtep.json"), buildLog.FormatForTraceEventProfiler()); } } long maximumCacheSize = ScriptableBuildPipeline.maximumCacheSize * 1073741824L; // gigabytes to bytes ThreadPool.QueueUserWorkItem(PruneCache, maximumCacheSize); return(exitCode); }
/// <inheritdoc /> public CacheEntry GetCacheEntry(GUID asset, int version = 1) { return(BuildCacheUtility.GetCacheEntry(asset, version)); }
/// <summary> /// Returns the Object Identifiers and Types in a raw Unity Serialized File. The resulting arrays will be empty if a non-serialized file path was used. /// </summary> /// <param name="path">Path to the Unity Serialized File</param> /// <param name="objectIdentifiers">Object Identifiers for all the objects in the serialized file</param> /// <param name="types">Types for all the objects in the serialized file</param> public void GetObjectIdentifiersAndTypesForSerializedFile(string path, out ObjectIdentifier[] objectIdentifiers, out Type[] types) { objectIdentifiers = ContentBuildInterface.GetPlayerObjectIdentifiersInSerializedFile(path, m_Parameters.Target); types = BuildCacheUtility.GetTypeForObjects(objectIdentifiers); }
public AutoBuildCacheUtility() { BuildCacheUtility.ClearCacheHashes(); }
/// <inheritdoc /> public CacheEntry GetCacheEntry(Type type, int version = 1) { return(BuildCacheUtility.GetCacheEntry(type, version)); }
public void Dispose() { BuildCacheUtility.ClearCacheHashes(); }
/// <inheritdoc /> public CacheEntry GetCacheEntry(string path, int version = 1) { return(BuildCacheUtility.GetCacheEntry(path, version)); }
/// <inheritdoc /> public ReturnCode Run() { if (m_Content.Scenes.IsNullOrEmpty()) { return(ReturnCode.SuccessNotRun); } IList <CachedInfo> cachedInfo = null; IList <CachedInfo> uncachedInfo = null; if (m_Parameters.UseCache && m_Cache != null) { IList <CacheEntry> entries = m_Content.Scenes.Select(x => m_Cache.GetCacheEntry(x, Version)).ToList(); m_Cache.LoadCachedData(entries, out cachedInfo); uncachedInfo = new List <CachedInfo>(); } BuildSettings settings = m_Parameters.GetContentBuildSettings(); for (int i = 0; i < m_Content.Scenes.Count; i++) { GUID scene = m_Content.Scenes[i]; string scenePath = AssetDatabase.GUIDToAssetPath(scene.ToString()); SceneDependencyInfo sceneInfo; BuildUsageTagSet usageTags; Hash128 prefabDependency = new Hash128(); if (cachedInfo != null && cachedInfo[i] != null) { if (!m_Tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", scenePath))) { return(ReturnCode.Canceled); } sceneInfo = (SceneDependencyInfo)cachedInfo[i].Data[0]; usageTags = cachedInfo[i].Data[1] as BuildUsageTagSet; prefabDependency = (Hash128)cachedInfo[i].Data[2]; var objectTypes = cachedInfo[i].Data[3] as List <KeyValuePair <ObjectIdentifier, System.Type[]> >; if (objectTypes != null) { BuildCacheUtility.SetTypeForObjects(objectTypes); } } else { if (!m_Tracker.UpdateInfoUnchecked(scenePath)) { return(ReturnCode.Canceled); } usageTags = new BuildUsageTagSet(); #if UNITY_2019_3_OR_NEWER sceneInfo = ContentBuildInterface.CalculatePlayerDependenciesForScene(scenePath, settings, usageTags, m_DependencyData.DependencyUsageCache); #else string outputFolder = m_Parameters.TempOutputFolder; if (m_Parameters.UseCache && m_Cache != null) { outputFolder = m_Cache.GetCachedArtifactsDirectory(m_Cache.GetCacheEntry(scene, Version)); } Directory.CreateDirectory(outputFolder); sceneInfo = ContentBuildInterface.PrepareScene(scenePath, settings, usageTags, m_DependencyData.DependencyUsageCache, outputFolder); #endif if (uncachedInfo != null) { // We only need to gather prefab dependencies and calculate the hash if we are using caching, otherwise we can skip it var prefabEntries = AssetDatabase.GetDependencies(AssetDatabase.GUIDToAssetPath(scene.ToString())).Where(path => path.EndsWith(".prefab")).Select(m_Cache.GetCacheEntry); prefabDependency = HashingMethods.Calculate(prefabEntries).ToHash128(); uncachedInfo.Add(GetCachedInfo(scene, sceneInfo.referencedObjects, sceneInfo, usageTags, prefabEntries, prefabDependency)); } } SetOutputInformation(scene, sceneInfo, usageTags, prefabDependency); } if (m_Parameters.UseCache && m_Cache != null) { m_Cache.SaveCachedData(uncachedInfo); } return(ReturnCode.Success); }