private bool IsAssetSprite(ref BuildCommandSet.AssetLoadInfo asset) { if (asset.referencedObjects.IsNullOrEmpty()) { return(false); } if (string.IsNullOrEmpty(asset.referencedObjects[0].filePath)) { return(false); } return(asset.referencedObjects[0].filePath.StartsWith(kUnityAtlasCachePath)); }
internal static BuildCommandSet.AssetLoadInfo CreatePrefabWithReferences(GUID prefabGuid, params ObjectIdentifier[] references) { var asset = new BuildCommandSet.AssetLoadInfo(); asset.address = prefabGuid.ToString(); asset.asset = prefabGuid; asset.processedScene = ""; asset.includedObjects = new[] { ConstructObjectIdentifier(prefabGuid, 1326890503170502, FileType.SerializedAssetType, ""), // GameObject ConstructObjectIdentifier(prefabGuid, 4326504406238768, FileType.SerializedAssetType, ""), // Transform ConstructObjectIdentifier(prefabGuid, 114305515917122674, FileType.SerializedAssetType, "") // Monobehavior W/ Reference }; List <ObjectIdentifier> referencedObjects = new List <ObjectIdentifier>(references); referencedObjects.Add(ConstructObjectIdentifier(new GUID("206794ec26056d846b1615847cacd2cc"), 11500000, FileType.MetaAssetType, "")); // MonoScript asset.referencedObjects = referencedObjects.ToArray(); return(asset); }
internal static BuildCommandSet.AssetLoadInfo CreateFBXWithMesh(GUID fbxGuid) { var asset = new BuildCommandSet.AssetLoadInfo(); asset.address = fbxGuid.ToString(); asset.asset = fbxGuid; asset.processedScene = ""; asset.includedObjects = new[] { ConstructObjectIdentifier(fbxGuid, 100000, FileType.MetaAssetType, ""), // GameObject ConstructObjectIdentifier(fbxGuid, 400000, FileType.MetaAssetType, ""), // Transform ConstructObjectIdentifier(fbxGuid, 2100000, FileType.MetaAssetType, ""), // Material ConstructObjectIdentifier(fbxGuid, 2300000, FileType.MetaAssetType, ""), // MeshRenderer ConstructObjectIdentifier(fbxGuid, 3300000, FileType.MetaAssetType, ""), // MeshFilter ConstructObjectIdentifier(fbxGuid, 4300000, FileType.MetaAssetType, "") // Mesh }; asset.referencedObjects = new[] { ConstructObjectIdentifier(new GUID("0000000000000000f000000000000000"), 6, FileType.NonAssetType, "resources/unity_builtin_extra"), // Shader ConstructObjectIdentifier(new GUID("0000000000000000f000000000000000"), 46, FileType.NonAssetType, "resources/unity_builtin_extra") // Shader }; return(asset); }
public static BuildCommandSet GenerateBuildCommandSet(BuildInput input, BuildSettings settings) { // Rebuild sprite atlas cache for correct dependency calculation Packer.RebuildAtlasCacheIfNeeded(settings.target, true, Packer.Execution.Normal); // Need to specal case sprites as we only want to include the source texutre in certain situations m_SpriteMap.Clear(); // Create commands array matching the size of the input var commandSet = new BuildCommandSet(); commandSet.commands = new BuildCommandSet.Command[input.definitions.Length]; for (var i = 0; i < input.definitions.Length; ++i) { var definition = input.definitions[i]; // Populate each command from asset bundle definition var command = new BuildCommandSet.Command(); command.assetBundleName = definition.assetBundleName; command.explicitAssets = new BuildCommandSet.AssetLoadInfo[definition.explicitAssets.Length]; // Fill out asset load info and references for each asset in the definition var allObjects = new HashSet <ObjectIdentifier>(); for (var j = 0; j < definition.explicitAssets.Length; ++j) { var explicitAsset = new BuildCommandSet.AssetLoadInfo(); explicitAsset.asset = definition.explicitAssets[j]; explicitAsset.path = AssetDatabase.GUIDToAssetPath(explicitAsset.asset.ToString()); explicitAsset.includedObjects = AssetBundleBuildInterface.GetObjectIdentifiersInAsset(definition.explicitAssets[j]); explicitAsset.referencedObjects = AssetBundleBuildInterface.GetPlayerDependenciesForObjects(explicitAsset.includedObjects); // Is this asset a sprite? var type = AssetDatabase.GetMainAssetTypeAtPath(explicitAsset.path); if (type == typeof(Texture2D) && explicitAsset.referencedObjects.Length == 1) { // Source texture should always be the first included object, atlas should always be the first referenced object m_SpriteMap[explicitAsset.referencedObjects[0].guid] = new StriteTextures(explicitAsset.includedObjects[0], explicitAsset.referencedObjects[0], command.assetBundleName); } command.explicitAssets[j] = explicitAsset; allObjects.UnionWith(explicitAsset.includedObjects); allObjects.UnionWith(explicitAsset.referencedObjects); } command.assetBundleObjects = allObjects.ToArray(); commandSet.commands[i] = command; } // TODO: Debug printing DebugPrintCommandSet(ref commandSet); // At this point, We have generated fully self contained asset bundles with 0 dependencies. // Default implementation is to reduce duplication of objects by declaring dependencies to other asset // bundles if that other asset bundle has an explicit asset declared that contains the objects needed // We also remove any built in unity objects as they are built with the player (We may want to change this part in the future) CalculateAssetBundleBuildDependencies(ref commandSet); // Note: I may, or may not feel dirty doing mutable things to what otherwise should be immutable struct // TODO: Debug printing DebugPrintCommandSet(ref commandSet); return(commandSet); }
public override BuildPipelineCodes Convert(BuildDependencyInformation input, BuildSettings settings, bool aggressive, out BuildDependencyInformation 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.assetLoadInfo.Values) { var dependencies = input.assetToBundles[asset.asset]; if (aggressive && !asset.includedObjects.IsNullOrEmpty()) { for (int i = 1; i < asset.includedObjects.Length; ++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 == CommandSetProcessor.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 BuildCommandSet.AssetLoadInfo(); assetInfo.asset = new GUID(hashPair.Key.ToString()); assetInfo.address = hashPair.Key.ToString(); assetInfo.includedObjects = hashPair.Value.ToArray(); assetInfo.referencedObjects = new ObjectIdentifier[0]; Array.Sort(assetInfo.includedObjects, (x, y) => { if (x < y) { return(-1); } if (x > y) { return(1); } return(0); }); // Add new AssetLoadInfo for virtual asset output.assetLoadInfo.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.assetLoadInfo[virtualAsset]; var dependencies = output.assetToBundles[virtualAsset]; var references = BundleBuildInterface.GetPlayerDependenciesForObjects(assetInfo.includedObjects, 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(BuildInput input, BuildSettings settings, out BuildDependencyInformation output) { StartProgressBar(input); output = new BuildDependencyInformation(); foreach (var bundle in input.definitions) { foreach (var asset in bundle.explicitAssets) { if (SceneDependency.ValidScene(asset.asset)) { if (!UpdateProgressBar(asset.asset)) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } // Get Scene Dependency Information SceneLoadInfo sceneInfo; BuildPipelineCodes errorCode = m_SceneDependency.Convert(asset.asset, settings, out sceneInfo); if (errorCode < BuildPipelineCodes.Success) { EndProgressBar(); return(errorCode); } // Convert Scene Dependency Information to Asset Load Information var assetInfo = new BuildCommandSet.AssetLoadInfo(); assetInfo.asset = asset.asset; assetInfo.address = string.IsNullOrEmpty(asset.address) ? AssetDatabase.GUIDToAssetPath(asset.asset.ToString()) : asset.address; assetInfo.processedScene = sceneInfo.processedScene; assetInfo.includedObjects = new ObjectIdentifier[0]; assetInfo.referencedObjects = sceneInfo.referencedObjects.ToArray(); // Add generated scene information to BuildDependencyInformation output.sceneResourceFiles.Add(asset.asset, sceneInfo.resourceFiles.ToArray()); output.sceneUsageTags.Add(asset.asset, sceneInfo.globalUsage); output.assetLoadInfo.Add(asset.asset, assetInfo); // Add the current bundle as dependency[0] List <string> bundles = new List <string>(); bundles.Add(bundle.assetBundleName); output.assetToBundles.Add(asset.asset, bundles); // Add the current asset to the list of assets for a bundle List <GUID> bundleAssets; output.bundleToAssets.GetOrAdd(bundle.assetBundleName, out bundleAssets); bundleAssets.Add(asset.asset); } else if (AssetDependency.ValidAsset(asset.asset)) { if (!UpdateProgressBar(asset.asset)) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } // Get Asset Dependency Information BuildCommandSet.AssetLoadInfo assetInfo; BuildPipelineCodes errorCode = m_AssetDependency.Convert(asset.asset, settings, out assetInfo); if (errorCode < BuildPipelineCodes.Success) { EndProgressBar(); return(errorCode); } // Convert Asset Dependency Information to Asset Load Information assetInfo.address = string.IsNullOrEmpty(asset.address) ? AssetDatabase.GUIDToAssetPath(asset.asset.ToString()) : asset.address; // Add generated scene information to BuildDependencyInformation output.assetLoadInfo.Add(asset.asset, assetInfo); // Add the current bundle as dependency[0] List <string> bundles = new List <string>(); bundles.Add(bundle.assetBundleName); output.assetToBundles.Add(asset.asset, bundles); // Add the current asset to the list of assets for a bundle List <GUID> bundleAssets; output.bundleToAssets.GetOrAdd(bundle.assetBundleName, out bundleAssets); bundleAssets.Add(asset.asset); } else { if (!UpdateProgressBar(asset.asset)) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } } } } if (!UpdateProgressBar("Calculating asset to bundle dependencies")) { EndProgressBar(); return(BuildPipelineCodes.Canceled); } // Generate the explicit asset to bundle dependency lookup foreach (var asset in output.assetLoadInfo.Values) { var assetBundles = output.assetToBundles[asset.asset]; foreach (var reference in asset.referencedObjects) { List <string> refBundles; if (!output.assetToBundles.TryGetValue(reference.guid, out refBundles)) { continue; } var dependency = refBundles[0]; if (assetBundles.Contains(dependency)) { continue; } assetBundles.Add(dependency); } } if (!EndProgressBar()) { return(BuildPipelineCodes.Canceled); } return(BuildPipelineCodes.Success); }