/// <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); }
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())); } }
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); }