void CreateSceneBundleCommand(string bundleName, string internalName, GUID scene, List <GUID> bundledScenes, Dictionary <GUID, string> assetToMainFile) { var fileObjects = m_WriteData.FileToObjects[internalName]; #if !UNITY_2019_1_OR_NEWER // ContentBuildInterface.PrepareScene was not returning stable sorted references, causing a indeterminism and loading errors in some cases // Add correct sorting here until patch lands to fix the API. fileObjects = GetSortedSceneObjectIdentifiers(fileObjects); #endif var command = CreateWriteCommand(internalName, fileObjects, new LinearPackedIdentifiers(3)); // Start at 3: PreloadData = 1, AssetBundle = 2 var usageSet = new BuildUsageTagSet(); var referenceMap = new BuildReferenceMap(); var preloadObjects = new List <ObjectIdentifier>(); var bundleScenes = new List <SceneLoadInfo>(); var dependencyInfo = m_DependencyData.SceneInfo[scene]; var fileObjectSet = new HashSet <ObjectIdentifier>(fileObjects); usageSet.UnionWith(m_DependencyData.SceneUsage[scene]); referenceMap.AddMappings(command.internalName, command.serializeObjects.ToArray()); foreach (var referencedObject in dependencyInfo.referencedObjects) { if (fileObjectSet.Contains(referencedObject)) { continue; } preloadObjects.Add(referencedObject); } foreach (var bundledScene in bundledScenes) { var loadInfo = new SceneLoadInfo(); loadInfo.asset = bundledScene; loadInfo.internalName = Path.GetFileNameWithoutExtension(assetToMainFile[bundledScene]); loadInfo.address = m_BuildContent.Addresses[bundledScene]; bundleScenes.Add(loadInfo); } var operation = new SceneBundleWriteOperation(); operation.Command = command; operation.UsageSet = usageSet; operation.ReferenceMap = referenceMap; operation.DependencyHash = m_DependencyData.DependencyHash.TryGetValue(scene, out var hash) ? hash : new Hash128(); operation.Scene = dependencyInfo.scene; #if !UNITY_2019_3_OR_NEWER operation.ProcessedScene = dependencyInfo.processedScene; #endif operation.PreloadInfo = new PreloadInfo(); operation.PreloadInfo.preloadObjects = preloadObjects; operation.Info = new SceneBundleInfo(); operation.Info.bundleName = bundleName; operation.Info.bundleScenes = bundleScenes; m_WriteData.WriteOperations.Add(operation); m_WriteData.FileToUsageSet.Add(command.internalName, usageSet); m_WriteData.FileToReferenceMap.Add(command.internalName, referenceMap); }
void CreateAssetBundleCommand(string bundleName, string internalName, List <GUID> assets) { var command = CreateWriteCommand(internalName, m_WriteData.FileToObjects[internalName], m_PackingMethod); var usageSet = new BuildUsageTagSet(); var referenceMap = new BuildReferenceMap(); var dependencyHashes = new List <Hash128>(); var bundleAssets = new List <AssetLoadInfo>(); referenceMap.AddMappings(command.internalName, command.serializeObjects.ToArray()); foreach (var asset in assets) { usageSet.UnionWith(m_DependencyData.AssetUsage[asset]); if (m_DependencyData.DependencyHash.TryGetValue(asset, out var hash)) { dependencyHashes.Add(hash); } AssetLoadInfo assetInfo = m_DependencyData.AssetInfo[asset]; assetInfo.address = m_BuildContent.Addresses[asset]; bundleAssets.Add(assetInfo); } bundleAssets.Sort(AssetLoadInfoCompare); var operation = new AssetBundleWriteOperation(); operation.Command = command; operation.UsageSet = usageSet; operation.ReferenceMap = referenceMap; operation.DependencyHash = !dependencyHashes.IsNullOrEmpty() ? HashingMethods.Calculate(dependencyHashes).ToHash128() : new Hash128(); operation.Info = new AssetBundleInfo(); operation.Info.bundleName = bundleName; operation.Info.bundleAssets = bundleAssets; m_WriteData.WriteOperations.Add(operation); m_WriteData.FileToUsageSet.Add(command.internalName, usageSet); m_WriteData.FileToReferenceMap.Add(command.internalName, referenceMap); }
public override WriteResult Write(string outputFolder, List <WriteCommand> dependencies, BuildSettings settings, BuildUsageTagGlobal globalUsage, BuildUsageTagSet buildUsage) { buildUsage.UnionWith(usageTags); return(BundleBuildInterface.WriteSceneSerializedFile(outputFolder, scene, processedScene, command, dependencies, settings, globalUsage, buildUsage, preloadInfo, info)); }
#pragma warning restore 649 /// <inheritdoc /> public ReturnCode Run() { Dictionary <string, WriteCommand> fileToCommand; Dictionary <string, HashSet <ObjectIdentifier> > forwardObjectDependencies; Dictionary <string, HashSet <string> > forwardFileDependencies; Dictionary <string, HashSet <GUID> > reverseAssetDependencies; // BuildReferenceMap details what objects exist in other bundles that objects in a source bundle depend upon (forward dependencies) // BuildUsageTagSet details the conditional data needed to be written by objects in a source bundle that is in used by objects in other bundles (reverse dependencies) using (m_Log.ScopedStep(LogLevel.Info, $"Temporary Map Creations")) { fileToCommand = m_WriteData.WriteOperations.ToDictionary(x => x.Command.internalName, x => x.Command); forwardObjectDependencies = new Dictionary <string, HashSet <ObjectIdentifier> >(); forwardFileDependencies = new Dictionary <string, HashSet <string> >(); reverseAssetDependencies = new Dictionary <string, HashSet <GUID> >(); foreach (var pair in m_WriteData.AssetToFiles) { GUID asset = pair.Key; List <string> files = pair.Value; // The includes for an asset live in the first file, references could live in any file forwardObjectDependencies.GetOrAdd(files[0], out HashSet <ObjectIdentifier> objectDependencies); forwardFileDependencies.GetOrAdd(files[0], out HashSet <string> fileDependencies); // Grab the list of object references for the asset or scene and add them to the forward dependencies hash set for this file (write command) if (m_DependencyData.AssetInfo.TryGetValue(asset, out AssetLoadInfo assetInfo)) { objectDependencies.UnionWith(assetInfo.referencedObjects); } if (m_DependencyData.SceneInfo.TryGetValue(asset, out SceneDependencyInfo sceneInfo)) { objectDependencies.UnionWith(sceneInfo.referencedObjects); } // Grab the list of file references for the asset or scene and add them to the forward dependencies hash set for this file (write command) // While doing so, also add the asset to the reverse dependencies hash set for all the other files it depends upon. // We already ensure BuildReferenceMap & BuildUsageTagSet contain the objects in this write command in GenerateBundleCommands. So skip over the first file (self) for (int i = 1; i < files.Count; i++) { fileDependencies.Add(files[i]); reverseAssetDependencies.GetOrAdd(files[i], out HashSet <GUID> reverseDependencies); reverseDependencies.Add(asset); } } } // Using the previously generated forward dependency maps, update the BuildReferenceMap per WriteCommand to contain just the references that we care about using (m_Log.ScopedStep(LogLevel.Info, $"Populate BuildReferenceMaps")) { foreach (var operation in m_WriteData.WriteOperations) { var internalName = operation.Command.internalName; BuildReferenceMap referenceMap = m_WriteData.FileToReferenceMap[internalName]; if (!forwardObjectDependencies.TryGetValue(internalName, out var objectDependencies)) { continue; // this bundle has no external dependencies } if (!forwardFileDependencies.TryGetValue(internalName, out var fileDependencies)) { continue; // this bundle has no external dependencies } foreach (string file in fileDependencies) { WriteCommand dependentCommand = fileToCommand[file]; foreach (var serializedObject in dependentCommand.serializeObjects) { // Only add objects we are referencing. This ensures that new/removed objects to files we depend upon will not cause a rebuild // of this file, unless are referencing the new/removed objects. if (!objectDependencies.Contains(serializedObject.serializationObject)) { continue; } referenceMap.AddMapping(file, serializedObject.serializationIndex, serializedObject.serializationObject); } } } } // Using the previously generate reverse dependency map, create the BuildUsageTagSet per WriteCommand to contain just the data that we care about using (m_Log.ScopedStep(LogLevel.Info, $"Populate BuildUsageTagSet")) { foreach (var operation in m_WriteData.WriteOperations) { var internalName = operation.Command.internalName; BuildUsageTagSet fileUsage = m_WriteData.FileToUsageSet[internalName]; if (reverseAssetDependencies.TryGetValue(internalName, out var assetDependencies)) { foreach (GUID asset in assetDependencies) { if (m_DependencyData.AssetUsage.TryGetValue(asset, out var assetUsage)) { fileUsage.UnionWith(assetUsage); } if (m_DependencyData.SceneUsage.TryGetValue(asset, out var sceneUsage)) { fileUsage.UnionWith(sceneUsage); } } } if (ReflectionExtensions.SupportsFilterToSubset) { fileUsage.FilterToSubset(m_WriteData.FileToObjects[internalName].ToArray()); } } } return(ReturnCode.Success); }