Esempio n. 1
0
        /// <summary>
        /// Utility method for creating locations from player data.
        /// </summary>
        /// <param name="assetGroup">The group to extract the locations from.</param>
        /// <param name="locations">The list of created locations to fill in.</param>
        /// <param name="providerTypes">Any unknown provider types are added to this set in order to ensure they are not stripped.</param>
        /// <returns>True if any legacy locations were created.  This is used by the build scripts to determine if a legacy provider is needed.</returns>
        protected bool CreateLocationsForPlayerData(PlayerDataGroupSchema playerDataSchema, AddressableAssetGroup assetGroup, List <ContentCatalogDataEntry> locations, HashSet <Type> providerTypes)
        {
            bool needsLegacyProvider = false;

            if (playerDataSchema != null && (playerDataSchema.IncludeBuildSettingsScenes || playerDataSchema.IncludeResourcesFolders))
            {
                var entries = new List <AddressableAssetEntry>();
                assetGroup.GatherAllAssets(entries, true, true, false);
                foreach (var a in entries)
                {
                    if (!playerDataSchema.IncludeBuildSettingsScenes && a.IsInSceneList)
                    {
                        continue;
                    }
                    if (!playerDataSchema.IncludeResourcesFolders && a.IsInResources)
                    {
                        continue;
                    }
                    a.CreateCatalogEntries(locations, false, a.IsScene ? "" : typeof(LegacyResourcesProvider).FullName, null, null, providerTypes);
                    if (!a.IsScene)
                    {
                        needsLegacyProvider = true;
                    }
                }
            }
            return(needsLegacyProvider);
        }
        internal static void CreateResourceLocationData(
            AddressableAssetGroup assetGroup,
            string bundleName,
            string bundleInternalId,
            string bundleProvider,
            string assetProvider,
            List <GUID> assetsInBundle,
            HashSet <string> bundleDependencies,
            List <ContentCatalogDataEntry> locations,
            HashSet <Type> providerTypes,
            IDependencyData dependencyData)
        {
            locations.Add(new ContentCatalogDataEntry(typeof(IAssetBundleResource), bundleInternalId, bundleProvider, new object[] { bundleName }));

            var assets = new List <AddressableAssetEntry>();

            assetGroup.GatherAllAssets(assets, true, true, false);
            var guidToEntry = new Dictionary <string, AddressableAssetEntry>();

            foreach (var a in assets)
            {
                guidToEntry.Add(a.guid, a);
            }
            foreach (var a in assetsInBundle)
            {
                AddressableAssetEntry entry;
                if (!guidToEntry.TryGetValue(a.ToString(), out entry))
                {
                    continue;
                }
                entry.CreateCatalogEntriesInternal(locations, true, assetProvider, bundleDependencies, null, dependencyData.AssetInfo);
            }
        }
        /// <summary>
        /// Utility method for creating locations from player data.
        /// </summary>
        /// <param name="assetGroup">The group to extract the locations from.</param>
        /// <param name="locations">The list of created locations to fill in.</param>
        /// <returns>True if any legacy locations were created.  This is used by the build scripts to determine if a legacy provider is needed.</returns>
        protected bool CreateLocationsForPlayerData(PlayerDataGroupSchema playerDataSchema, AddressableAssetGroup assetGroup, List <ContentCatalogDataEntry> locations)
        {
            bool needsLegacyProvider = false;

            if (playerDataSchema != null && (playerDataSchema.IncludeBuildSettingsScenes || playerDataSchema.IncludeResourcesFolders))
            {
                var entries = new List <AddressableAssetEntry>();
                assetGroup.GatherAllAssets(entries, true, true);
                foreach (var a in entries)
                {
                    if (!playerDataSchema.IncludeBuildSettingsScenes && a.IsInSceneList)
                    {
                        continue;
                    }
                    if (!playerDataSchema.IncludeResourcesFolders && a.IsInResources)
                    {
                        continue;
                    }
                    string providerId = a.IsScene ? "" : typeof(LegacyResourcesProvider).FullName;
                    locations.Add(new ContentCatalogDataEntry(a.GetAssetLoadPath(false), providerId, a.CreateKeyList()));
                    if (!a.IsScene)
                    {
                        needsLegacyProvider = true;
                    }
                }
            }
            return(needsLegacyProvider);
        }
Esempio n. 4
0
        internal static void CreateResourceLocationData(
            AddressableAssetGroup assetGroup,
            string bundleName,
            string bundleInternalId,
            string bundleProvider,
            string assetProvider,
            List <GUID> assetsInBundle,
            Dictionary <GUID, List <string> > assetsToBundles,
            List <ContentCatalogDataEntry> locations)
        {
            locations.Add(new ContentCatalogDataEntry(bundleInternalId, bundleProvider, new object[] { bundleName }));

            var assets = new List <AddressableAssetEntry>();

            assetGroup.GatherAllAssets(assets, true, true);
            var guidToEntry = new Dictionary <string, AddressableAssetEntry>();

            foreach (var a in assets)
            {
                guidToEntry.Add(a.guid, a);
            }

            foreach (var a in assetsInBundle)
            {
                AddressableAssetEntry entry;
                if (!guidToEntry.TryGetValue(a.ToString(), out entry))
                {
                    continue;
                }
                var assetPath = entry.GetAssetLoadPath(true);
                locations.Add(new ContentCatalogDataEntry(assetPath, assetProvider, entry.CreateKeyList(), assetsToBundles[a].ToArray()));
            }
        }
Esempio n. 5
0
    internal static List <AssetEntryRevertOperation> DetermineRequiredAssetEntryUpdates(AddressableAssetGroup group, ContentUpdateScript.ContentUpdateContext contentUpdateContext)
    {
        if (!group.HasSchema <BundledAssetGroupSchema>())
        {
            return(new List <AssetEntryRevertOperation>());
        }

        bool groupIsStaticContentGroup = group.HasSchema <ContentUpdateGroupSchema>() && group.GetSchema <ContentUpdateGroupSchema>().StaticContent;
        List <AssetEntryRevertOperation> operations = new List <AssetEntryRevertOperation>();

        List <AddressableAssetEntry> allEntries = new List <AddressableAssetEntry>();

        group.GatherAllAssets(allEntries, true, true, false);
        foreach (AddressableAssetEntry entry in allEntries)
        {
            if (entry.IsFolder)
            {
                continue;
            }
            GUID guid = new GUID(entry.guid);
            if (!contentUpdateContext.WriteData.AssetToFiles.ContainsKey(guid))
            {
                continue;
            }

            string file = contentUpdateContext.WriteData.AssetToFiles[guid][0];
            string fullInternalBundleName = contentUpdateContext.WriteData.FileToBundle[file];
            string finalBundleWritePath   = contentUpdateContext.BundleToInternalBundleIdMap[fullInternalBundleName];

            //Ensure we can get the catalog entry for the bundle we're looking to replace
            if (!contentUpdateContext.IdToCatalogDataEntryMap.TryGetValue(finalBundleWritePath, out ContentCatalogDataEntry catalogBundleEntry))
            {
                continue;
            }

            //If new entries are added post initial build this will ensure that those new entries have their bundleFileId for SaveContentState
            entry.BundleFileId = catalogBundleEntry.InternalId;

            //If we have no cached state no reason to proceed.  This is new to the build.
            if (!contentUpdateContext.GuidToPreviousAssetStateMap.TryGetValue(entry.guid, out CachedAssetState previousAssetState))
            {
                continue;
            }

            //If the parent group is different we don't want to revert it to its previous state
            if (entry.parentGroup.Guid != previousAssetState.groupGuid)
            {
                continue;
            }

            //If the asset hash has changed and the group is not a static content update group we don't want to revert it to its previous state
            if (AssetDatabase.GetAssetDependencyHash(entry.AssetPath) != previousAssetState.asset.hash && !groupIsStaticContentGroup)
            {
                continue;
            }

            //If the previous asset state has the same bundle file id as the current build we don't want to revert it to its previous state
            if (catalogBundleEntry.InternalId == previousAssetState.bundleFileId)
            {
                continue;
            }

            var    schema    = group.GetSchema <BundledAssetGroupSchema>();
            string loadPath  = schema.LoadPath.GetValue(group.Settings);
            string buildPath = schema.BuildPath.GetValue(group.Settings);

            //Need to check and make sure our cached version exists
            if (string.IsNullOrEmpty(previousAssetState.bundleFileId))
            {
                //Logging this as an error because a CachedAssetState without a set bundleFileId is indicative of a significant issue with the build script.
                Addressables.LogError($"CachedAssetState found for {entry.AssetPath} but the bundleFileId was never set on the previous build.");
                continue;
            }

            string previousBundlePath = BundleIdToBuildPath(previousAssetState.bundleFileId, loadPath, buildPath);
            if (!File.Exists(previousBundlePath))
            {
                //Logging this as a warning because users may choose to delete their bundles on disk which will trigger this state.
                Addressables.LogWarning($"CachedAssetState found for {entry.AssetPath} but the previous bundle at {previousBundlePath} cannot be found. " +
                                        $"This will not affect loading the bundle in previously built players, but loading the missing bundle in Play Mode using the play mode script " +
                                        $"\"Use Existing Build (requires built groups)\" will fail.");
            }

            string builtBundlePath = BundleIdToBuildPath(contentUpdateContext.BundleToInternalBundleIdMap[fullInternalBundleName], loadPath, buildPath);

            AssetEntryRevertOperation operation = new AssetEntryRevertOperation()
            {
                BundleCatalogEntry = catalogBundleEntry,
                AssetEntry         = entry,
                CurrentBuildPath   = builtBundlePath,
                PreviousAssetState = previousAssetState,
                PreviousBuildPath  = previousBundlePath
            };

            operations.Add(operation);
        }
        return(operations);
    }