Пример #1
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        /// <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));
        }
Пример #5
0
        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);
        }
Пример #7
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }