private void WriteSerialziedFiles(string bundleName, IWriteOperation op, List <WriteCommand> allCommands, BuildSettings settings, BuildUsageTagGlobal globalUsage, ref List <WriteResult> outResults) { WriteResult result; var dependencies = op.CalculateDependencies(allCommands); var objectIDs = op.command.serializeObjects.Select(x => x.serializationObject).ToArray(); var dependentIDs = dependencies.SelectMany(x => x.serializeObjects.Select(y => y.serializationObject)).ToArray(); BuildUsageTagSet buildUsage = new BuildUsageTagSet(); BundleBuildInterface.CalculateBuildUsageTags(objectIDs, dependentIDs, globalUsage, buildUsage); Hash128 hash = CalculateInputHash(op, dependencies, settings, globalUsage, buildUsage); if (UseCache && BuildCache.TryLoadCachedResults(hash, out result)) { outResults.Add(result); return; } result = op.Write(GetBuildPath(hash), dependencies, settings, globalUsage, buildUsage); outResults.Add(result); if (UseCache && !BuildCache.SaveCachedResults(hash, result)) { BuildLogger.LogWarning("Unable to cache CommandSetWriter results for command '{0}'.", op.command.internalName); } }
public override BuildPipelineCodes Convert(AssetBundleBuild[] input, out BuildInput output) { StartProgressBar(input); // If enabled, try loading from cache var hash = CalculateInputHash(input); if (UseCache && BuildCache.TryLoadCachedResults(hash, out output)) { EndProgressBar(); return(BuildPipelineCodes.SuccessCached); } // Convert inputs output = new BuildInput(); if (input.IsNullOrEmpty()) { BuildLogger.LogError("Unable to continue packing. Input is null or empty!"); EndProgressBar(); return(BuildPipelineCodes.Error); } output.definitions = new BuildInput.Definition[input.Length]; for (var i = 0; i < input.Length; i++) { output.definitions[i].assetBundleName = input[i].assetBundleName; output.definitions[i].explicitAssets = new AssetIdentifier[input[i].assetNames.Length]; for (var j = 0; j < input.Length; j++) { UpdateProgressBar(input[i].assetNames[j]); var guid = AssetDatabase.AssetPathToGUID(input[i].assetNames[j]); output.definitions[i].explicitAssets[j].asset = new GUID(guid); if (input[i].addressableNames.IsNullOrEmpty() || input[i].addressableNames.Length <= j || string.IsNullOrEmpty(input[i].addressableNames[j])) { output.definitions[i].explicitAssets[j].address = input[i].assetNames[j]; } else { output.definitions[i].explicitAssets[j].address = input[i].addressableNames[j]; } } } // Cache results if (UseCache && !BuildCache.SaveCachedResults(hash, output)) { BuildLogger.LogWarning("Unable to cache AssetBundleBuildConverter results."); } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }
public override BuildPipelineCodes Convert(GUID asset, BuildSettings settings, out AssetLoadInfo output) { StartProgressBar("Calculating Asset Dependencies", 2); if (!ValidAsset(asset)) { output = new AssetLoadInfo(); EndProgressBar(); return(BuildPipelineCodes.Error); } Hash128 hash = CalculateInputHash(asset, settings); if (UseCache && BuildCache.TryLoadCachedResults(hash, out output)) { if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.SuccessCached); } output = new AssetLoadInfo(); output.asset = asset; if (!UpdateProgressBar("Calculating included objects")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } output.includedObjects = new List <ObjectIdentifier>(BundleBuildInterface.GetPlayerObjectIdentifiersInAsset(asset, settings.target)); if (!UpdateProgressBar("Calculating referenced objects")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } output.referencedObjects = new List <ObjectIdentifier>(BundleBuildInterface.GetPlayerDependenciesForObjects(output.includedObjects.ToArray(), settings.target, settings.typeDB)); if (UseCache && !BuildCache.SaveCachedResults(hash, output)) { BuildLogger.LogWarning("Unable to cache AssetDependency results for asset '{0}'.", asset); } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }
public override BuildPipelineCodes Convert(BuildDependencyInfo buildInfo, out BuildWriteInfo writeInfo) { StartProgressBar("Generating Build Commands", buildInfo.bundleToAssets.Count); Hash128 hash = CalculateInputHash(buildInfo); if (UseCache && BuildCache.TryLoadCachedResults(hash, out writeInfo)) { writeInfo = new BuildWriteInfo(); EndProgressBar(); return(BuildPipelineCodes.SuccessCached); } writeInfo = new BuildWriteInfo(); foreach (var bundle in buildInfo.bundleToAssets) { if (!UpdateProgressBar("Generating Build Commands")) { return(BuildPipelineCodes.Canceled); } // TODO: Handle Player Data & Raw write formats if (IsAssetBundle(bundle.Value)) { var op = CreateAssetBundleWriteOperation(bundle.Key, bundle.Value, buildInfo); writeInfo.assetBundles.Add(bundle.Key, op); } else if (IsSceneBundle(bundle.Value)) { var ops = CreateSceneBundleWriteOperations(bundle.Key, bundle.Value, buildInfo); writeInfo.sceneBundles.Add(bundle.Key, ops); } else { BuildLogger.LogError("Bundle '{0}' contains mixed assets and scenes.", bundle.Key); } } if (UseCache && !BuildCache.SaveCachedResults(hash, writeInfo)) { BuildLogger.LogWarning("Unable to cache CommandSetProcessor results."); } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }
public override BuildPipelineCodes Convert(GUID scene, BuildSettings settings, BuildUsageTagSet usageSet, out SceneDependencyInfo output) { StartProgressBar("Calculating Scene Dependencies", 1); if (!ValidScene(scene)) { output = new SceneDependencyInfo(); EndProgressBar(); return(BuildPipelineCodes.Error); } var scenePath = AssetDatabase.GUIDToAssetPath(scene.ToString()); if (!UpdateProgressBar(scenePath)) { output = new SceneDependencyInfo(); EndProgressBar(); return(BuildPipelineCodes.Canceled); } Hash128 hash = CalculateInputHash(scene, settings); if (UseCache && BuildCache.TryLoadCachedResults(hash, out output) && BuildCache.TryLoadCachedResults(hash, out usageSet)) { if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.SuccessCached); } output = BundleBuildInterface.PrepareScene(scenePath, settings, usageSet, GetBuildPath(hash)); if (UseCache && !BuildCache.SaveCachedResults(hash, output) && !BuildCache.SaveCachedResults(hash, usageSet)) { BuildLogger.LogWarning("Unable to cache SceneDependency results for asset '{0}'.", scene); } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }
public override BuildPipelineCodes Convert(BuildCommandSet commandSet, BuildSettings settings, out List <WriteResult> output) { StartProgressBar("Writing Resource Files", commandSet.commands.Count); CacheDataForCommandSet(commandSet); output = new List <WriteResult>(); foreach (var command in commandSet.commands) { if (!UpdateProgressBar(string.Format("Bundle: {0}", command.assetBundleName))) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } BuildOutput result; Hash128 hash = CalculateInputHash(command, settings); if (UseCache && BuildCache.TryLoadCachedResults(hash, out result)) { output.AddRange(result.results); continue; } result = BundleBuildInterface.WriteResourceFilesForBundle(commandSet, command.assetBundleName, settings, GetBuildPath(hash)); output.AddRange(result.results); if (UseCache && !BuildCache.SaveCachedResults(hash, result)) { BuildLogger.LogWarning("Unable to cache CommandSetWriter results for command '{0}'.", command.assetBundleName); } } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }
public override BuildPipelineCodes Convert(BuildDependencyInformation buildInfo, out BuildCommandSet output) { StartProgressBar("Generating Build Commands", buildInfo.assetLoadInfo.Count); Hash128 hash = CalculateInputHash(buildInfo); if (UseCache && BuildCache.TryLoadCachedResults(hash, out output)) { output = new BuildCommandSet(); EndProgressBar(); return(BuildPipelineCodes.SuccessCached); } var commands = new List <BuildCommandSet.Command>(); foreach (var bundle in buildInfo.bundleToAssets) { var command = new BuildCommandSet.Command(); var explicitAssets = new List <BuildCommandSet.AssetLoadInfo>(); var assetBundleObjects = new List <BuildCommandSet.SerializationInfo>(); var dependencies = new HashSet <string>(); foreach (var asset in bundle.Value) { var assetInfo = buildInfo.assetLoadInfo[asset]; explicitAssets.Add(assetInfo); if (!UpdateProgressBar(assetInfo.asset)) { output = new BuildCommandSet(); EndProgressBar(); return(BuildPipelineCodes.Canceled); } dependencies.UnionWith(buildInfo.assetToBundles[asset]); foreach (var includedObject in assetInfo.includedObjects) { if (!buildInfo.virtualAssets.Contains(asset) && buildInfo.objectToVirtualAsset.ContainsKey(includedObject)) { continue; } assetBundleObjects.Add(new BuildCommandSet.SerializationInfo { serializationObject = includedObject, serializationIndex = SerializationIndexFromObjectIdentifier(includedObject) }); } foreach (var referencedObject in assetInfo.referencedObjects) { if (referencedObject.filePath == kUnityDefaultResourcePath) { continue; } if (buildInfo.objectToVirtualAsset.ContainsKey(referencedObject)) { continue; } if (buildInfo.assetLoadInfo.ContainsKey(referencedObject.guid)) { continue; } assetBundleObjects.Add(new BuildCommandSet.SerializationInfo { serializationObject = referencedObject, serializationIndex = SerializationIndexFromObjectIdentifier(referencedObject) }); } BuildUsageTagGlobal globalUsage; if (buildInfo.sceneUsageTags.TryGetValue(asset, out globalUsage)) { command.sceneBundle = true; command.globalUsage |= globalUsage; } } dependencies.Remove(bundle.Key); assetBundleObjects.Sort(Compare); command.assetBundleName = bundle.Key; command.explicitAssets = explicitAssets.ToArray(); command.assetBundleDependencies = dependencies.OrderBy(x => x).ToArray(); command.assetBundleObjects = assetBundleObjects.ToArray(); commands.Add(command); } output = new BuildCommandSet(); output.commands = commands.ToArray(); if (UseCache && !BuildCache.SaveCachedResults(hash, output)) { BuildLogger.LogWarning("Unable to cache CommandSetProcessor results."); } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }
private void SaveToCache(Hash128 hash, BuildInput output) { BuildCache.SaveCachedResults(hash, output); }
public override BuildPipelineCodes Convert(BuildDependencyInfo input, BuildSettings settings, bool aggressive, out BuildDependencyInfo output) { StartProgressBar("Generated shared object bundles", 3); Hash128 hash = CalculateInputHash(input); if (UseCache && BuildCache.TryLoadCachedResults(hash, out output)) { EndProgressBar(); return(BuildPipelineCodes.SuccessCached); } // Mutating the input output = input; if (!UpdateProgressBar("Generate lookup of all objects")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } // Generate mapping of each object to the bundles it would be used by var objectToBundles = new Dictionary <ObjectIdentifier, HashSet <string> >(); var objectToAssets = new Dictionary <ObjectIdentifier, HashSet <GUID> >(); foreach (var asset in input.assetInfo.Values) { var dependencies = input.assetToBundles[asset.asset]; if (aggressive && !asset.includedObjects.IsNullOrEmpty()) { for (int i = 1; i < asset.includedObjects.Count; ++i) { var objectID = asset.includedObjects[i]; HashSet <string> bundles; objectToBundles.GetOrAdd(objectID, out bundles); bundles.Add(dependencies[0]); HashSet <GUID> assets; objectToAssets.GetOrAdd(objectID, out assets); assets.Add(asset.asset); } } foreach (var referenceID in asset.referencedObjects) { if (!aggressive && input.assetToBundles.ContainsKey(referenceID.guid)) { continue; } if (referenceID.filePath == BuildWriteProcessor.kUnityDefaultResourcePath) { continue; } HashSet <string> bundles; objectToBundles.GetOrAdd(referenceID, out bundles); bundles.Add(dependencies[0]); HashSet <GUID> assets; objectToAssets.GetOrAdd(referenceID, out assets); assets.Add(asset.asset); } } if (!UpdateProgressBar("Finding set of reused objects")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } // Generate the set of reused objects var hashToObjects = new Dictionary <Hash128, List <ObjectIdentifier> >(); foreach (var objectPair in objectToBundles) { if (objectPair.Value.Count <= 1) { continue; } var bundleHash = HashingMethods.CalculateMD5Hash(objectPair.Value.ToArray()); List <ObjectIdentifier> objectIDs; hashToObjects.GetOrAdd(bundleHash, out objectIDs); objectIDs.Add(objectPair.Key); } if (!UpdateProgressBar("Creating shared object bundles")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } // Generate Shared Bundles foreach (var hashPair in hashToObjects) { // Generate Dependency Information for virtual asset var assetInfo = new AssetLoadInfo(); assetInfo.asset = new GUID(hashPair.Key.ToString()); assetInfo.address = hashPair.Key.ToString(); assetInfo.includedObjects = hashPair.Value.ToList(); assetInfo.referencedObjects = new List <ObjectIdentifier>(); assetInfo.includedObjects.Sort((x, y) => { if (x < y) { return(-1); } if (x > y) { return(1); } return(0); }); // Add new AssetLoadInfo for virtual asset output.assetInfo.Add(assetInfo.asset, assetInfo); var assetBundles = new List <string>(); assetBundles.Add(assetInfo.address); // Add new bundle as dependency[0] for virtual asset output.assetToBundles.Add(assetInfo.asset, assetBundles); var bundleAssets = new List <GUID>(); bundleAssets.Add(assetInfo.asset); // Add virtual asset to the list of assets for new bundle output.bundleToAssets.Add(assetInfo.address, bundleAssets); // Add virtual asset to lookup output.virtualAssets.Add(assetInfo.asset); foreach (var objectID in assetInfo.includedObjects) { // Add objects in virtual asset to lookup output.objectToVirtualAsset.Add(objectID, assetInfo.asset); var assets = objectToAssets[objectID]; foreach (var asset in assets) { if (!output.assetToBundles.TryGetValue(asset, out assetBundles)) { continue; } if (assetBundles.Contains(assetInfo.address)) { continue; } // Add new bundle as dependency to assets referencing virtual asset objects assetBundles.Add(assetInfo.address); } } } // Generate Shared Bundle Build Dependencies foreach (var virtualAsset in output.virtualAssets) { var assetInfo = output.assetInfo[virtualAsset]; var dependencies = output.assetToBundles[virtualAsset]; var references = BundleBuildInterface.GetPlayerDependenciesForObjects(assetInfo.includedObjects.ToArray(), settings.target, settings.typeDB); foreach (var reference in references) { GUID dependency; List <string> bundles; string depStr = ""; // If the reference is to an object in a virtual asset, no major checks, just add it as a dependency if (output.objectToVirtualAsset.TryGetValue(reference, out dependency)) { if (dependency == virtualAsset) { continue; } depStr = dependency.ToString(); } // Otherwise if this reference is part of an asset assigned to a bundle, then set the bundle as a dependency to the virtual asset else if (output.assetToBundles.TryGetValue(reference.guid, out bundles)) { if (bundles.IsNullOrEmpty()) { continue; } depStr = bundles[0]; } if (dependencies.Contains(depStr)) { continue; } dependencies.Add(depStr); } } if (UseCache && !BuildCache.SaveCachedResults(hash, output)) { BuildLogger.LogWarning("Unable to cache SharedObjectProcessor results."); } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }
public override BuildPipelineCodes Convert(AssetInfoMap assetLoadInfo, out AssetInfoMap output) { StartProgressBar("Stripping unused sprite source textures", 3); if (!UpdateProgressBar("Finding sprite source textures")) { output = null; return(BuildPipelineCodes.Canceled); } var spriteRefCount = new Dictionary <ObjectIdentifier, int>(); foreach (var assetInfo in assetLoadInfo) { var path = AssetDatabase.GUIDToAssetPath(assetInfo.Value.asset.ToString()); var importer = AssetImporter.GetAtPath(path) as TextureImporter; if (importer != null && importer.textureType == TextureImporterType.Sprite && !string.IsNullOrEmpty(importer.spritePackingTag)) { spriteRefCount[assetInfo.Value.includedObjects[0]] = 0; } } Hash128 hash = CalculateInputHash(assetLoadInfo, spriteRefCount); if (UseCache && BuildCache.TryLoadCachedResults(hash, out output)) { EndProgressBar(); return(BuildPipelineCodes.SuccessCached); } // Mutating the input, this is the only converter that does this output = assetLoadInfo; if (!UpdateProgressBar("Finding sprite source textures usage")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } foreach (var assetInfo in output) { if (!string.IsNullOrEmpty(assetInfo.Value.processedScene)) { continue; } foreach (var reference in assetInfo.Value.referencedObjects) { int refCount = 0; if (!spriteRefCount.TryGetValue(reference, out refCount)) { continue; } // Note: Because pass by value spriteRefCount[reference] = ++refCount; } } if (!UpdateProgressBar("Removing unused sprite source textures.")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } foreach (var source in spriteRefCount) { if (source.Value > 0) { continue; } var assetInfo = output[source.Key.guid]; var includedObjects = assetInfo.includedObjects; includedObjects.RemoveAt(0); } if (UseCache && !BuildCache.SaveCachedResults(hash, output)) { BuildLogger.LogWarning("Unable to cache SpriteSourceProcessor results."); } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }