public static ObjectIdentifier[] FilterReferencedObjectIDs(GUID asset, ObjectIdentifier[] references, BuildTarget target, TypeDB typeDB, HashSet <GUID> dependencies) { // Expectation: references is populated with DependencyType.ValidReferences only for the given asset var collectedImmediateReferences = new HashSet <ObjectIdentifier>(); var encounteredDependencies = new HashSet <ObjectIdentifier>(); while (references.Length > 0) { // Track which roots we encounter to do dependency pruning encounteredDependencies.UnionWith(references.Where(x => x.guid != asset && dependencies.Contains(x.guid))); // We only want to recursively grab references for objects being pulled in and won't go to another bundle ObjectIdentifier[] immediateReferencesNotInOtherBundles = references.Where(x => !dependencies.Contains(x.guid) && !collectedImmediateReferences.Contains(x)).ToArray(); collectedImmediateReferences.UnionWith(immediateReferencesNotInOtherBundles); // Grab next set of valid references and loop references = ContentBuildInterface.GetPlayerDependenciesForObjects(immediateReferencesNotInOtherBundles, target, typeDB, DependencyType.ValidReferences); } // We need to ensure that we have a reference to a visible representation so our runtime dependency appending process // can find something that can be appended, otherwise the necessary data will fail to load correctly in all cases. (EX: prefab A has reference to component on prefab B) foreach (var dependency in encounteredDependencies) { // For each dependency, add just the main representation as a reference var representations = ContentBuildInterface.GetPlayerAssetRepresentations(dependency.guid, target); collectedImmediateReferences.Add(representations.First()); } collectedImmediateReferences.UnionWith(encounteredDependencies); return(collectedImmediateReferences.ToArray()); }
public void CreateAssetEntryForObjectIdentifiers(ObjectIdentifier[] includedObjects, string path, string bundleName, string address, Type mainAssetType) { AssetLoadInfo assetInfo = new AssetLoadInfo(); BuildUsageTagSet usageTags = new BuildUsageTagSet(); assetInfo.asset = HashingMethods.Calculate(address).ToGUID(); if (m_DependencyData.AssetInfo.ContainsKey(assetInfo.asset)) { throw new ArgumentException(string.Format("Custom Asset '{0}' already exists. Building duplicate asset entries is not supported.", address)); } assetInfo.includedObjects = new List <ObjectIdentifier>(includedObjects); var referencedObjects = ContentBuildInterface.GetPlayerDependenciesForObjects(includedObjects, m_Parameters.Target, m_Parameters.ScriptInfo); assetInfo.referencedObjects = new List <ObjectIdentifier>(referencedObjects); ContentBuildInterface.CalculateBuildUsageTags(referencedObjects, includedObjects, m_GlobalUsage, usageTags, m_DependencyData.DependencyUsageCache); List <GUID> assets; m_Content.BundleLayout.GetOrAdd(bundleName, out assets); assets.Add(assetInfo.asset); m_Content.Addresses[assetInfo.asset] = address; m_Content.FakeAssets[assetInfo.asset] = path; SetOutputInformation(assetInfo.asset, assetInfo, usageTags); }
void GatherAssetData(string path, out AssetLoadInfo assetInfo, out BuildUsageTagSet buildUsage, BuildUsageTagGlobal globalUsage) { assetInfo = new AssetLoadInfo(); buildUsage = new BuildUsageTagSet(); var includedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInSerializedFile(path, m_Parameters.Target); var referencedObjects = ContentBuildInterface.GetPlayerDependenciesForObjects(includedObjects, m_Parameters.Target, m_Parameters.ScriptInfo); assetInfo.includedObjects = new List <ObjectIdentifier>(includedObjects); assetInfo.referencedObjects = new List <ObjectIdentifier>(referencedObjects); ContentBuildInterface.CalculateBuildUsageTags(referencedObjects, includedObjects, globalUsage, buildUsage, m_DependencyData.DependencyUsageCache); }
/// <summary> /// 查找某个资源引用到的资源 /// </summary> /// <param name="typeDB">可以通过<see cref="EditorExtend.CompilePlayerScriptsUtility.CompileCurrentTargetTypeDB"/>获取</param> /// <param name="buildTarget">如果为NoTarget 则使用当前的平台</param> public static ObjectIdentifier[] SearchAssetDependenciesWithAssetGUID(string assetGUID, TypeDB typeDB = null, BuildTarget buildTarget = BuildTarget.NoTarget) { if (buildTarget == BuildTarget.NoTarget) { buildTarget = EditorUserBuildSettings.activeBuildTarget; } if (typeDB == null) { CompilePlayerScriptsUtility.GetOrCompileCurrentTargetTypeDB(false, out typeDB); } ObjectIdentifier[] assetIncludes = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(assetGUID), buildTarget); return(ContentBuildInterface.GetPlayerDependenciesForObjects(assetIncludes, buildTarget, typeDB)); }
static CachedInfo CalculateTargetCachedInfo(CacheEntry entry, BuildTarget target, TypeDB typeDB = null) { var cache = new BuildCache(); List <ObjectIdentifier> objects = new List <ObjectIdentifier>(); objects.AddRange(ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(entry.Guid, target)); objects.AddRange(ContentBuildInterface.GetPlayerDependenciesForObjects(objects.ToArray(), target, typeDB)); var cachedInfo = new CachedInfo(); cachedInfo.Asset = entry; cachedInfo.Data = new[] { objects }; // TODO: Handle built-in objects, might require some low level build changes like an option to ignore the hideFlags var dependencies = objects.Select(x => x.guid).Where(x => !x.Empty() && x != entry.Guid && x != k_UnityBuiltinResources).Distinct(); cachedInfo.Dependencies = dependencies.Select(cache.GetCacheEntry).ToArray(); // cache.SaveCachedData(new List<CachedInfo> { cachedInfo }); // TODO: Disabled because we have file contention as "Save" is async only with no wait functionality return(cachedInfo); }
/// <inheritdoc /> public ReturnCode Run() { 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>(); } 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; 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; } else { if (!m_Tracker.UpdateInfoUnchecked(scenePath)) { return(ReturnCode.Canceled); } var references = new HashSet <ObjectIdentifier>(); string[] dependencies = AssetDatabase.GetDependencies(scenePath); foreach (var assetPath in dependencies) { var assetGuid = new GUID(AssetDatabase.AssetPathToGUID(assetPath)); if (ValidationMethods.ValidAsset(assetGuid) != ValidationMethods.Status.Asset) { continue; } // TODO: Use Cache to speed this up? var assetIncludes = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(assetGuid, m_Parameters.Target); var assetReferences = ContentBuildInterface.GetPlayerDependenciesForObjects(assetIncludes, m_Parameters.Target, m_Parameters.ScriptInfo); references.UnionWith(assetIncludes); references.UnionWith(assetReferences); } sceneInfo = new SceneDependencyInfo(); usageTags = new BuildUsageTagSet(); sceneInfo.SetScene(scenePath); sceneInfo.SetProcessedScene(scenePath); sceneInfo.SetReferencedObjects(references.ToArray()); if (uncachedInfo != null) { uncachedInfo.Add(GetCachedInfo(scene, sceneInfo.referencedObjects, sceneInfo, usageTags)); } } SetOutputInformation(scene, sceneInfo, usageTags); } if (m_Parameters.UseCache && m_Cache != null) { m_Cache.SaveCachedData(uncachedInfo); } return(ReturnCode.Success); }
public ReturnCode Run() { var globalUsage = m_DependencyData.GlobalUsage; foreach (SceneDependencyInfo sceneInfo in m_DependencyData.SceneInfo.Values) { globalUsage |= sceneInfo.globalUsage; } if (m_SpriteData == null) { m_SpriteData = new BuildSpriteData(); } IList <CachedInfo> cachedInfo = null; List <CachedInfo> uncachedInfo = null; if (m_Parameters.UseCache && m_Cache != null) { IList <CacheEntry> entries = m_Content.Assets.Select(m_Cache.GetCacheEntry).ToList(); m_Cache.LoadCachedData(entries, out cachedInfo); uncachedInfo = new List <CachedInfo>(); } for (int i = 0; i < m_Content.Assets.Count; i++) { GUID asset = m_Content.Assets[i]; string assetPath = AssetDatabase.GUIDToAssetPath(asset.ToString()); AssetLoadInfo assetInfo; BuildUsageTagSet usageTags; SpriteImporterData importerData; if (cachedInfo != null && cachedInfo[i] != null) { if (!m_Tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", assetPath))) { return(ReturnCode.Canceled); } assetInfo = cachedInfo[i].Data[0] as AssetLoadInfo; usageTags = cachedInfo[i].Data[1] as BuildUsageTagSet; importerData = cachedInfo[i].Data[2] as SpriteImporterData; } else { if (!m_Tracker.UpdateInfoUnchecked(assetPath)) { return(ReturnCode.Canceled); } assetInfo = new AssetLoadInfo(); usageTags = new BuildUsageTagSet(); importerData = null; assetInfo.asset = asset; var includedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(asset, m_Parameters.Target); assetInfo.includedObjects = new List <ObjectIdentifier>(includedObjects); var referencedObjects = ContentBuildInterface.GetPlayerDependenciesForObjects(includedObjects, m_Parameters.Target, m_Parameters.ScriptInfo); assetInfo.referencedObjects = new List <ObjectIdentifier>(referencedObjects); ContentBuildInterface.CalculateBuildUsageTags(referencedObjects, includedObjects, globalUsage, usageTags, m_DependencyData.DependencyUsageCache); var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (importer != null && importer.textureType == TextureImporterType.Sprite) { importerData = new SpriteImporterData(); importerData.PackedSprite = !string.IsNullOrEmpty(importer.spritePackingTag); importerData.SourceTexture = includedObjects.First(); } if (uncachedInfo != null) { uncachedInfo.Add(GetCachedInfo(asset, assetInfo, usageTags, importerData)); } } SetOutputInformation(asset, assetInfo, usageTags, importerData); } if (m_SpriteData.ImporterData.Count == 0) { m_SpriteData = null; } if (m_Parameters.UseCache && m_Cache != null) { m_Cache.SaveCachedData(uncachedInfo); } return(ReturnCode.Success); }
public static bool BuildAssetBundle(string manifestPath, GUID assetGuid, string cacheFilePath, BuildTarget target, HashSet <Entities.Hash128> dependencies, HashSet <System.Type> types, long fileIdent) { using (new BuildInterfacesWrapper()) { Directory.CreateDirectory(k_TempBuildPath); // Used for naming var fixedGUID = assetGuid; if (fileIdent != -1) { GUIDHelper.PackBuiltinExtraWithFileIdent(ref fixedGUID, fileIdent); } string assetGUIDString = fixedGUID.ToString(); // Deterministic ID Generator var generator = new Unity5PackedIdentifiers(); // Target platform settings & script information var settings = new BuildSettings { buildFlags = ContentBuildFlags.None, target = target, group = BuildPipeline.GetBuildTargetGroup(target), typeDB = null }; if (assetGuid == GUIDHelper.UnityBuiltinResources) { FilterBuiltinResourcesObjectManifest(manifestPath); } if (assetGuid == GUIDHelper.UnityBuiltinExtraResources) { FilterBuiltinExtraResourcesObjectManifest(manifestPath); } // Collect all the objects we need for this asset & bundle (returned array order is deterministic) var manifestObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInSerializedFile(manifestPath, settings.target); // Collect all the objects we need to reference for this asset (returned array order is deterministic) var manifestDependencies = ContentBuildInterface.GetPlayerDependenciesForObjects(manifestObjects, settings.target, settings.typeDB); // Scene / Project lighting information var globalUsage = ContentBuildInterface.GetGlobalUsageFromGraphicsSettings(); globalUsage = ForceKeepInstancingVariants(globalUsage); // Inter-asset feature usage (shader features, used mesh channels) var usageSet = new BuildUsageTagSet(); ContentBuildInterface.CalculateBuildUsageTags(manifestDependencies, manifestDependencies, globalUsage, usageSet); // TODO: Cache & Append to the assets that are influenced by this usageTagSet, ideally it would be a nice api to extract just the data for a given asset or object from the result // Bundle all the needed write parameters var writeParams = new WriteParameters { // Target platform settings & script information settings = settings, // Scene / Project lighting information globalUsage = globalUsage, // Inter-asset feature usage (shader features, used mesh channels) usageSet = usageSet, // Serialized File Layout writeCommand = new WriteCommand { fileName = generator.GenerateInternalFileName(assetGUIDString), internalName = generator.GenerateAssetBundleInternalFileName(fixedGUID), serializeObjects = new List <SerializationInfo>() // Populated Below }, // External object references referenceMap = new BuildReferenceMap(), // Populated Below // Asset Bundle object layout bundleInfo = new AssetBundleInfo { bundleName = assetGUIDString, // What is loadable from this bundle bundleAssets = new List <AssetLoadInfo> { // The manifest object and it's dependencies new AssetLoadInfo { address = assetGUIDString, asset = assetGuid, // TODO: Remove this as it is unused in C++ includedObjects = manifestObjects.ToList(), // TODO: In our effort to modernize the public API design we over complicated it trying to take List or return ReadOnlyLists. Should have just stuck with Arrays[] in all places referencedObjects = manifestDependencies.ToList() } } } }; // The requirement is that a single asset bundle only contains the ObjectManifest and the objects that are directly part of the asset, objects for external assets will be in their own bundles. IE: 1 asset per bundle layout // So this means we need to take manifestObjects & manifestDependencies and filter storing them into writeCommand.serializeObjects and/or referenceMap based on if they are this asset or other assets // For the Manifest Objects, we only have the ScriptableObject `AssetObjectManifest` which is not referenced outside of this bundle. // This creates a deterministic ID for it, regardless of the path of the manifest file var linearGenerator = new LinearPackedIdentifiers(2); foreach (var obj in manifestObjects) { var index = linearGenerator.SerializationIndexFromObjectIdentifier(obj); writeParams.writeCommand.serializeObjects.Add(new SerializationInfo { serializationObject = obj, serializationIndex = index }); writeParams.referenceMap.AddMapping(writeParams.writeCommand.internalName, index, obj); } foreach (var obj in manifestDependencies) { // MonoScripts need to live beside the MonoBehavior (in this case ScriptableObject) and loaded first. We could move it to it's own bundle, but this is safer and it's a lightweight object var type = ContentBuildInterface.GetTypeForObject(obj); if (obj.guid == GUIDHelper.UnityBuiltinResources) { // For Builtin Resources, we can reference them directly // TODO: Once we switch to using GlobalObjectId for SBP, we will need a mapping for certain special cases of GUID <> FilePath for Builtin Resources writeParams.referenceMap.AddMapping(obj.filePath, obj.localIdentifierInFile, obj); } else if (type == typeof(MonoScript)) { writeParams.writeCommand.serializeObjects.Add(new SerializationInfo { serializationObject = obj, serializationIndex = generator.SerializationIndexFromObjectIdentifier(obj) }); writeParams.referenceMap.AddMapping(writeParams.writeCommand.internalName, generator.SerializationIndexFromObjectIdentifier(obj), obj); } else if (obj.guid == assetGuid) { // If we are a specific built-in asset, only add the built-in asset if (fileIdent != -1 && obj.localIdentifierInFile != fileIdent) { continue; } writeParams.writeCommand.serializeObjects.Add(new SerializationInfo { serializationObject = obj, serializationIndex = generator.SerializationIndexFromObjectIdentifier(obj) }); writeParams.referenceMap.AddMapping(writeParams.writeCommand.internalName, generator.SerializationIndexFromObjectIdentifier(obj), obj); } else if (obj.guid == GUIDHelper.UnityBuiltinExtraResources) { var convGUID = obj.guid; GUIDHelper.PackBuiltinExtraWithFileIdent(ref convGUID, obj.localIdentifierInFile); writeParams.referenceMap.AddMapping(generator.GenerateAssetBundleInternalFileName(convGUID), generator.SerializationIndexFromObjectIdentifier(obj), obj); dependencies.Add(convGUID); } else if (!obj.guid.Empty()) { writeParams.referenceMap.AddMapping(generator.GenerateAssetBundleInternalFileName(obj.guid), generator.SerializationIndexFromObjectIdentifier(obj), obj); dependencies.Add(obj.guid); } else { throw new Exception($"Invalid dependency! GUID={obj.guid}, type={type}"); } if (type != null) { types.Add(type); } } // Write the serialized file var result = ContentBuildInterface.WriteSerializedFile(k_TempBuildPath, writeParams); // Archive and compress the serialized & resource files for the previous operation var crc = ContentBuildInterface.ArchiveAndCompress(result.resourceFiles.ToArray(), cacheFilePath, UnityEngine.BuildCompression.Uncompressed); // Because the shader compiler progress bar hooks are absolute shit EditorUtility.ClearProgressBar(); //Debug.Log($"Wrote '{writeParams.writeCommand.fileName}' to '{k_TempBuildPath}/{writeParams.writeCommand.internalName}' resulting in {result.serializedObjects.Count} objects in the serialized file."); //Debug.Log($"Archived '{k_TempBuildPath}/{writeParams.writeCommand.internalName}' to '{cacheFilePath}' resulting in {crc} CRC."); return(crc != 0); } }
public static void BuildSubSceneBundle(string manifestPath, string bundleName, string bundlePath, BuildTarget target, HashSet <Entities.Hash128> dependencies) { using (new BuildInterfacesWrapper()) { Directory.CreateDirectory(k_TempBuildPath); // Deterministic ID Generator var generator = new Unity5PackedIdentifiers(); // Target platform settings & script information var buildSettings = new BuildSettings { buildFlags = ContentBuildFlags.None, target = target, group = BuildPipeline.GetBuildTargetGroup(target), typeDB = null }; #if UNITY_2020_1_OR_NEWER // Collect all the objects we need for this asset & bundle (returned array order is deterministic) var manifestObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInSerializedFile(manifestPath, buildSettings.target); #else var method = typeof(ContentBuildInterface).GetMethod("GetPlayerObjectIdentifiersInSerializedFile", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); // Collect all the objects we need for this asset & bundle (returned array order is deterministic) var manifestObjects = (ObjectIdentifier[])method.Invoke(null, new object[] { manifestPath, buildSettings.target }); #endif // Collect all the objects we need to reference for this asset (returned array order is deterministic) var manifestDependencies = ContentBuildInterface.GetPlayerDependenciesForObjects(manifestObjects, buildSettings.target, buildSettings.typeDB); // Scene / Project lighting information var globalUsage = ContentBuildInterface.GetGlobalUsageFromGraphicsSettings(); globalUsage = ForceKeepInstancingVariants(globalUsage); // Inter-asset feature usage (shader features, used mesh channels) var usageSet = new BuildUsageTagSet(); ContentBuildInterface.CalculateBuildUsageTags(manifestDependencies, manifestDependencies, globalUsage, usageSet); // TODO: Cache & Append to the assets that are influenced by this usageTagSet, ideally it would be a nice api to extract just the data for a given asset or object from the result // Bundle all the needed write parameters var writeParams = new WriteParameters { // Target platform settings & script information settings = buildSettings, // Scene / Project lighting information globalUsage = globalUsage, // Inter-asset feature usage (shader features, used mesh channels) usageSet = usageSet, // Serialized File Layout writeCommand = new WriteCommand { fileName = generator.GenerateInternalFileName(bundleName), internalName = generator.GenerateAssetBundleInternalFileName(bundleName), serializeObjects = new List <SerializationInfo>() // Populated Below }, // External object references referenceMap = new BuildReferenceMap(), // Populated Below // Asset Bundle object layout bundleInfo = new AssetBundleInfo { bundleName = bundleName, // What is loadable from this bundle bundleAssets = new List <AssetLoadInfo> { // The manifest object and it's dependencies new AssetLoadInfo { address = bundleName, asset = new GUID(), // TODO: Remove this as it is unused in C++ includedObjects = manifestObjects .ToList(), // TODO: In our effort to modernize the public API design we over complicated it trying to take List or return ReadOnlyLists. Should have just stuck with Arrays[] in all places referencedObjects = manifestDependencies.ToList() } } } }; // The requirement is that a single asset bundle only contains the ObjectManifest and the objects that are directly part of the asset, objects for external assets will be in their own bundles. IE: 1 asset per bundle layout // So this means we need to take manifestObjects & manifestDependencies and filter storing them into writeCommand.serializeObjects and/or referenceMap based on if they are this asset or other assets foreach (var obj in manifestObjects) { writeParams.writeCommand.serializeObjects.Add(new SerializationInfo { serializationObject = obj, serializationIndex = generator.SerializationIndexFromObjectIdentifier(obj) }); writeParams.referenceMap.AddMapping(writeParams.writeCommand.internalName, generator.SerializationIndexFromObjectIdentifier(obj), obj); } foreach (var obj in manifestDependencies) { // MonoScripts need to live beside the MonoBehavior (in this case ScriptableObject) and loaded first. We could move it to it's own bundle, but this is safer and it's a lightweight object var type = ContentBuildInterface.GetTypeForObject(obj); if (obj.guid == k_UnityBuiltinResources) { // For Builtin Resources, we can reference them directly // TODO: Once we switch to using GlobalObjectId for SBP, we will need a mapping for certain special cases of GUID <> FilePath for Builtin Resources writeParams.referenceMap.AddMapping(obj.filePath, obj.localIdentifierInFile, obj); } else if (type == typeof(MonoScript)) { writeParams.writeCommand.serializeObjects.Add(new SerializationInfo { serializationObject = obj, serializationIndex = generator.SerializationIndexFromObjectIdentifier(obj) }); writeParams.referenceMap.AddMapping(writeParams.writeCommand.internalName, generator.SerializationIndexFromObjectIdentifier(obj), obj); } else if (!obj.guid.Empty()) { writeParams.referenceMap.AddMapping( generator.GenerateAssetBundleInternalFileName(obj.guid.ToString()), generator.SerializationIndexFromObjectIdentifier(obj), obj); } // This will be solvable after we move SBP into the asset pipeline as importers. if (!obj.guid.Empty() && type != typeof(MonoScript)) { var convGUID = obj.guid; if (obj.guid == k_UnityBuiltinExtraResources) { PackBuiltinExtraWithFileIdent(ref convGUID, obj.localIdentifierInFile); } dependencies?.Add(convGUID); } } // Write the serialized file var result = ContentBuildInterface.WriteSerializedFile(k_TempBuildPath, writeParams); // Archive and compress the serialized & resource files for the previous operation var crc = ContentBuildInterface.ArchiveAndCompress(result.resourceFiles.ToArray(), bundlePath, UnityEngine.BuildCompression.Uncompressed); // Because the shader compiler progress bar hooks are absolute shit EditorUtility.ClearProgressBar(); //Debug.Log($"Wrote '{writeParams.writeCommand.fileName}' to '{k_TempBuildPath}/{writeParams.writeCommand.internalName}' resulting in {result.serializedObjects.Count} objects in the serialized file."); //Debug.Log($"Archived '{k_TempBuildPath}/{writeParams.writeCommand.internalName}' to '{cacheFilePath}' resulting in {crc} CRC."); Directory.Delete(k_TempBuildPath, true); } }
public ReturnCode Run() { var globalUsage = m_DependencyData.GlobalUsage; foreach (SceneDependencyInfo sceneInfo in m_DependencyData.SceneInfo.Values) { globalUsage |= sceneInfo.globalUsage; } if (m_SpriteData == null) { m_SpriteData = new BuildSpriteData(); } if (m_ExtendedAssetData == null) { m_ExtendedAssetData = new BuildExtendedAssetData(); } IList <CachedInfo> cachedInfo = null; List <CachedInfo> uncachedInfo = null; if (m_Parameters.UseCache && m_Cache != null) { IList <CacheEntry> entries = m_Content.Assets.Select(x => m_Cache.GetCacheEntry(x, Version)).ToList(); m_Cache.LoadCachedData(entries, out cachedInfo); uncachedInfo = new List <CachedInfo>(); } for (int i = 0; i < m_Content.Assets.Count; i++) { GUID asset = m_Content.Assets[i]; string assetPath = AssetDatabase.GUIDToAssetPath(asset.ToString()); AssetLoadInfo assetInfo; BuildUsageTagSet usageTags; SpriteImporterData importerData; ExtendedAssetData assetData; if (cachedInfo != null && cachedInfo[i] != null) { if (!m_Tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", assetPath))) { return(ReturnCode.Canceled); } assetInfo = cachedInfo[i].Data[0] as AssetLoadInfo; usageTags = cachedInfo[i].Data[1] as BuildUsageTagSet; importerData = cachedInfo[i].Data[2] as SpriteImporterData; assetData = cachedInfo[i].Data[3] as ExtendedAssetData; } else { if (!m_Tracker.UpdateInfoUnchecked(assetPath)) { return(ReturnCode.Canceled); } assetInfo = new AssetLoadInfo(); usageTags = new BuildUsageTagSet(); importerData = null; assetData = null; assetInfo.asset = asset; var includedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(asset, m_Parameters.Target); assetInfo.includedObjects = new List <ObjectIdentifier>(includedObjects); var referencedObjects = ContentBuildInterface.GetPlayerDependenciesForObjects(includedObjects, m_Parameters.Target, m_Parameters.ScriptInfo); assetInfo.referencedObjects = new List <ObjectIdentifier>(referencedObjects); var allObjects = new List <ObjectIdentifier>(includedObjects); allObjects.AddRange(referencedObjects); ContentBuildInterface.CalculateBuildUsageTags(allObjects.ToArray(), includedObjects, globalUsage, usageTags, m_DependencyData.DependencyUsageCache); var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (importer != null && importer.textureType == TextureImporterType.Sprite) { // Legacy Sprite Packing Modes if (EditorSettings.spritePackerMode == SpritePackerMode.AlwaysOn || EditorSettings.spritePackerMode == SpritePackerMode.BuildTimeOnly) { importerData = new SpriteImporterData(); importerData.PackedSprite = !string.IsNullOrEmpty(importer.spritePackingTag); importerData.SourceTexture = includedObjects.First(); } else if (!referencedObjects.IsNullOrEmpty()) // Sprite is referencing packed data { importerData = new SpriteImporterData(); importerData.PackedSprite = EditorSettings.spritePackerMode != SpritePackerMode.Disabled; importerData.SourceTexture = includedObjects.First(); } } var representations = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetPath); if (!representations.IsNullOrEmpty()) { assetData = new ExtendedAssetData(); foreach (var representation in representations) { if (AssetDatabase.IsMainAsset(representation)) { continue; } string guid; long localId; if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(representation, out guid, out localId)) { continue; } assetData.Representations.AddRange(includedObjects.Where(x => x.localIdentifierInFile == localId)); } } if (uncachedInfo != null) { uncachedInfo.Add(GetCachedInfo(asset, assetInfo, usageTags, importerData, assetData)); } } SetOutputInformation(asset, assetInfo, usageTags, importerData, assetData); } if (m_SpriteData.ImporterData.Count == 0) { m_SpriteData = null; } if (m_ExtendedAssetData.ExtendedData.Count == 0) { m_SpriteData = null; } if (m_Parameters.UseCache && m_Cache != null) { m_Cache.SaveCachedData(uncachedInfo); } return(ReturnCode.Success); }
static internal ReturnCode RunInternal(TaskInput input, out TaskOutput output) { #if !UNITY_2020_2_OR_NEWER input.EngineHooks = input.EngineHooks != null ? input.EngineHooks : new CalculateAssetDependencyHooks(); #endif output = new TaskOutput(); output.AssetResults = new AssetOutput[input.Assets.Count]; IList <CachedInfo> cachedInfo = null; if (input.BuildCache != null) { IList <CacheEntry> entries = input.Assets.Select(x => input.BuildCache.GetCacheEntry(x, kVersion)).ToList(); input.BuildCache.LoadCachedData(entries, out cachedInfo); } using (input.Logger.ScopedStep(LogLevel.Info, "Calculate Dependencies")) { for (int i = 0; i < input.Assets.Count; i++) { AssetOutput assetResult = new AssetOutput(); assetResult.asset = input.Assets[i]; if (cachedInfo != null && cachedInfo[i] != null) { assetResult.assetInfo = cachedInfo[i].Data[0] as AssetLoadInfo; assetResult.usageTags = cachedInfo[i].Data[1] as BuildUsageTagSet; assetResult.spriteData = cachedInfo[i].Data[2] as SpriteImporterData; assetResult.extendedData = cachedInfo[i].Data[3] as ExtendedAssetData; assetResult.objectTypes = cachedInfo[i].Data[4] as List <KeyValuePair <ObjectIdentifier, System.Type[]> >; output.AssetResults[i] = assetResult; output.CachedAssetCount++; continue; } GUID asset = input.Assets[i]; string assetPath = AssetDatabase.GUIDToAssetPath(asset.ToString()); if (!input.ProgressTracker.UpdateInfoUnchecked(assetPath)) { return(ReturnCode.Canceled); } assetResult.assetInfo = new AssetLoadInfo(); assetResult.usageTags = new BuildUsageTagSet(); assetResult.assetInfo.asset = asset; var includedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(asset, input.Target); assetResult.assetInfo.includedObjects = new List <ObjectIdentifier>(includedObjects); var referencedObjects = ContentBuildInterface.GetPlayerDependenciesForObjects(includedObjects, input.Target, input.TypeDB); assetResult.assetInfo.referencedObjects = new List <ObjectIdentifier>(referencedObjects); var allObjects = new List <ObjectIdentifier>(includedObjects); allObjects.AddRange(referencedObjects); ContentBuildInterface.CalculateBuildUsageTags(allObjects.ToArray(), includedObjects, input.GlobalUsage, assetResult.usageTags, input.DependencyUsageCache); var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (importer != null && importer.textureType == TextureImporterType.Sprite) { assetResult.spriteData = new SpriteImporterData(); assetResult.spriteData.PackedSprite = false; assetResult.spriteData.SourceTexture = includedObjects.FirstOrDefault(); if (EditorSettings.spritePackerMode != SpritePackerMode.Disabled) { assetResult.spriteData.PackedSprite = referencedObjects.Length > 0; } #if !UNITY_2020_1_OR_NEWER if (EditorSettings.spritePackerMode == SpritePackerMode.AlwaysOn || EditorSettings.spritePackerMode == SpritePackerMode.BuildTimeOnly) { assetResult.spriteData.PackedSprite = !string.IsNullOrEmpty(importer.spritePackingTag); } #endif } #if !UNITY_2020_2_OR_NEWER GatherAssetRepresentations(assetPath, input.EngineHooks.LoadAllAssetRepresentationsAtPath, includedObjects, out assetResult.extendedData); #else GatherAssetRepresentations(asset, input.Target, out assetResult.extendedData); #endif output.AssetResults[i] = assetResult; } } if (input.BuildCache != null) { List <CachedInfo> toCache = new List <CachedInfo>(); for (int i = 0; i < input.Assets.Count; i++) { AssetOutput r = output.AssetResults[i]; if (cachedInfo[i] == null) { toCache.Add(GetCachedInfo(input.BuildCache, input.Assets[i], r.assetInfo, r.usageTags, r.spriteData, r.extendedData)); } } input.BuildCache.SaveCachedData(toCache); } return(ReturnCode.Success); }
static internal ReturnCode RunInternal(TaskInput input, out TaskOutput output) { input.EngineHooks = input.EngineHooks != null ? input.EngineHooks : new CalculateAssetDependencyHooks(); output = new TaskOutput(); output.AssetResults = new AssetOutput[input.Assets.Count]; IList <CachedInfo> cachedInfo = null; if (input.BuildCache != null) { IList <CacheEntry> entries = input.Assets.Select(x => input.BuildCache.GetCacheEntry(x, kVersion)).ToList(); input.BuildCache.LoadCachedData(entries, out cachedInfo); } for (int i = 0; i < input.Assets.Count; i++) { AssetOutput assetResult = new AssetOutput(); assetResult.asset = input.Assets[i]; if (cachedInfo != null && cachedInfo[i] != null) { assetResult.assetInfo = cachedInfo[i].Data[0] as AssetLoadInfo; assetResult.usageTags = cachedInfo[i].Data[1] as BuildUsageTagSet; assetResult.spriteData = cachedInfo[i].Data[2] as SpriteImporterData; assetResult.extendedData = cachedInfo[i].Data[3] as ExtendedAssetData; output.AssetResults[i] = assetResult; output.CachedAssetCount++; continue; } GUID asset = input.Assets[i]; string assetPath = AssetDatabase.GUIDToAssetPath(asset.ToString()); if (!input.ProgressTracker.UpdateInfoUnchecked(assetPath)) { return(ReturnCode.Canceled); } assetResult.assetInfo = new AssetLoadInfo(); assetResult.usageTags = new BuildUsageTagSet(); assetResult.assetInfo.asset = asset; var includedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(asset, input.Target); assetResult.assetInfo.includedObjects = new List <ObjectIdentifier>(includedObjects); var referencedObjects = ContentBuildInterface.GetPlayerDependenciesForObjects(includedObjects, input.Target, input.TypeDB); assetResult.assetInfo.referencedObjects = new List <ObjectIdentifier>(referencedObjects); var allObjects = new List <ObjectIdentifier>(includedObjects); allObjects.AddRange(referencedObjects); ContentBuildInterface.CalculateBuildUsageTags(allObjects.ToArray(), includedObjects, input.GlobalUsage, assetResult.usageTags, input.DependencyUsageCache); var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (importer != null && importer.textureType == TextureImporterType.Sprite) { assetResult.spriteData = new SpriteImporterData(); assetResult.spriteData.PackedSprite = false; assetResult.spriteData.SourceTexture = includedObjects.First(); if (EditorSettings.spritePackerMode != SpritePackerMode.Disabled) { assetResult.spriteData.PackedSprite = referencedObjects.Length > 0; } #if !UNITY_2020_1_OR_NEWER if (EditorSettings.spritePackerMode == SpritePackerMode.AlwaysOn || EditorSettings.spritePackerMode == SpritePackerMode.BuildTimeOnly) { assetResult.spriteData.PackedSprite = !string.IsNullOrEmpty(importer.spritePackingTag); } #endif } var representations = input.EngineHooks.LoadAllAssetRepresentationsAtPath(assetPath); if (!representations.IsNullOrEmpty()) { assetResult.extendedData = new ExtendedAssetData(); for (int j = 0; j < representations.Length; j++) { if (representations[j] == null) { BuildLogger.LogWarning($"SubAsset {j} inside {assetPath} is null. It will not be included in the build."); continue; } if (AssetDatabase.IsMainAsset(representations[j])) { continue; } string guid; long localId; if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(representations[j], out guid, out localId)) { continue; } assetResult.extendedData.Representations.AddRange(includedObjects.Where(x => x.localIdentifierInFile == localId)); } } output.AssetResults[i] = assetResult; } if (input.BuildCache != null) { List <CachedInfo> toCache = new List <CachedInfo>(); for (int i = 0; i < input.Assets.Count; i++) { AssetOutput r = output.AssetResults[i]; if (cachedInfo[i] == null) { toCache.Add(GetCachedInfo(input.BuildCache, input.Assets[i], r.assetInfo, r.usageTags, r.spriteData, r.extendedData)); } } input.BuildCache.SaveCachedData(toCache); } return(ReturnCode.Success); }