private static void ProcessAssetGroup(string assetPath) { AssetImporter ai = AssetImporter.GetAtPath(assetPath); if (ai == null) { Log.e("Not Find Asset:" + assetPath); return; } string fullPath = EditorUtils.AssetsPath2ABSPath(assetPath); if (Directory.Exists(fullPath)) { return; } string groupName = string.Empty; string dirName = Path.GetDirectoryName(assetPath); string assetBundleName = EditorUtils.AssetPath2ReltivePath(dirName).ToLower(); assetBundleName = assetBundleName.Replace("addressableres/", ""); if (assetPath.Contains("FolderMode")) { groupName = assetBundleName; } else { groupName = setting.DefaultGroup.name; } groupName = groupName.Replace("/", "-"); var group = setting.FindGroup(groupName); if (group == null) { //Debug.LogError("ProcessAssetGroup:" + groupName); group = setting.CreateGroup(groupName, false, false, false, new List <AddressableAssetGroupSchema> { setting.DefaultGroup.Schemas[0] }, typeof(SchemaType)); } if (group == null) { return; } var guid = AssetDatabase.AssetPathToGUID(assetPath); var entry = setting.CreateOrMoveEntry(guid, group); entry.SetAddress(PathHelper.FileNameWithoutSuffix(Path.GetFileName(assetPath)), true); //EditorUtility.SetDirty(setting); }
public void RunResourcesTestWithAsset(bool IncludeResourcesFolders) { int builtInResourceCount = ResourcesTestUtility.GetResourcesEntryCount(m_Settings, true); var path = GetPath("Resources/test.asset"); var dir = Path.GetDirectoryName(path); Directory.CreateDirectory(dir); AssetDatabase.CreateAsset(UnityEngine.AddressableAssets.Tests.TestObject.Create("test"), path); AssetDatabase.SaveAssets(); m_Settings.FindGroup(g => g.HasSchema <PlayerDataGroupSchema>()).GetSchema <PlayerDataGroupSchema>().IncludeResourcesFolders = IncludeResourcesFolders; var locator = new AddressableAssetSettingsLocator(m_Settings); var res = locator.Locate("test", null, out var locations); Assert.AreEqual(res, IncludeResourcesFolders); if (IncludeResourcesFolders) { Assert.AreEqual(1 + builtInResourceCount, locations.Count + builtInResourceCount); } else { Assert.IsNull(locations); } AssetDatabase.DeleteAsset(path); Directory.Delete(dir); }
void ImportGroupInternal(AddressableAssetSettings settings, string groupPath) { if (string.IsNullOrEmpty(groupPath) || Path.GetExtension(groupPath).ToLower() != ".asset" || !File.Exists(groupPath)) { Debug.LogError($"Group at '{groupPath}' not a valid group asset. Group will not be imported."); return; } AddressableAssetGroup oldGroup = AssetDatabase.LoadAssetAtPath <AddressableAssetGroup>(groupPath); if (oldGroup == null) { Debug.LogError($"Cannot load group asset at '{groupPath}'. Group will not be imported."); return; } if (settings.FindGroup(oldGroup.Name) != null) { Debug.LogError($"Settings already contains group '{oldGroup.Name}'. Group will not be imported."); return; } string groupFileName = Path.GetFileName(groupPath); string newGroupPath = $"{settings.GroupFolder}/{groupFileName}"; newGroupPath = newGroupPath.Replace("\\", "/"); if (File.Exists(newGroupPath)) { Debug.LogError($"File already exists at '{newGroupPath}'. Group will not be imported."); return; } if (!AssetDatabase.CopyAsset(groupPath, newGroupPath)) { Debug.LogError("Failed to copy group asset. Importing group failed."); } }
/// <summary> /// Get the compressions settings for the specified asset bundle. /// </summary> /// <param name="identifier">The identifier of the asset bundle.</param> /// <returns>The compression setting for the asset group. If the group is not found, the default compression is used.</returns> public override BuildCompression GetCompressionForIdentifier(string identifier) { string groupGuid; if (m_bundleToAssetGroup.TryGetValue(identifier, out groupGuid)) { var group = m_settings.FindGroup(g => g.Guid == groupGuid); if (group != null) { var abSchema = group.GetSchema <BundledAssetGroupSchema>(); if (abSchema != null) { return(abSchema.GetBuildCompressionForBundle(identifier)); } else { Debug.LogWarningFormat("Bundle group {0} does not have BundledAssetGroupSchema.", group.name); } } else { Debug.LogWarningFormat("Unable to find group with guid {0}", groupGuid); } } return(base.GetCompressionForIdentifier(identifier)); }
static AddressableAssetGroup GetGroupFromBundle(string bundleName, Dictionary <string, string> bundleToAssetGroupGUID, AddressableAssetSettings settings) { if (!bundleToAssetGroupGUID.TryGetValue(bundleName, out string groupGuid)) { return(settings.DefaultGroup); } return(settings.FindGroup(g => g != null && g.Guid == groupGuid)); }
public AddressableAssetGroupInfo GetGroupInfo(string groupGuid) { var group = _settings.FindGroup(x => x.Guid.Equals(groupGuid)); if (group == null) { throw new Exception( $"Failed to get {nameof(AddressableAssetGroup)} (GUID:{groupGuid}) because it does not exists."); } return(new AddressableAssetGroupInfo(group.Guid, group.Name)); }
protected virtual AddressableAssetGroup GetGroup(AddressableAssetSettings settings, string groupName, bool create = false) { var group = settings.FindGroup(groupName); if (group == null && create) { group = settings.CreateGroup(groupName, false, false, true, null, typeof(BundledAssetGroupSchema)); } return(group); }
/// <summary> ///创建分组 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="groupName"></param> /// <returns></returns> public static AddressableAssetGroup FindOrCreateGroup(string groupName) { AddressableAssetSettings Settings = AddressableAssetSettingsDefaultObject.Settings; AddressableAssetGroup group = Settings.FindGroup(groupName); if (group == null) { group = Settings.CreateGroup(groupName, false, false, false, null); } //Settings.AddLabel(groupName, false); return(group); }
void CacheImages() { var target = (ImageCacheSettings)base.target; this.addressable_settings = AddressableAssetSettingsDefaultObject.GetSettings(true); var group = addressable_settings.FindGroup(target.addressableGroupName); if (group == null) { Debug.LogError("Addressable group \"" + target.addressableGroupName + "\" not found."); return; } var entries = new HashSet <AddressableAssetEntry>(group.entries); foreach (var entry in entries) { group.RemoveAssetEntry(entry); } this.addressable_group = group; AssetDatabase.DeleteAsset("Assets/ImageCache"); AssetDatabase.CreateFolder("Assets", "ImageCache"); ((ImageCacheSettings)target).mapItems = new List <ImageCacheSettings.MapItem>(); var patterns = ((ImageCacheSettings)target).matchingPatterns; foreach (var path in AssetDatabase.GetAllAssetPaths()) { foreach (var regex in patterns) { if (Regex.IsMatch(path, regex)) { CacheImage(path); break; } } } EditorUtility.SetDirty(target); AssetDatabase.SaveAssets(); //AddressablesPlayerBuildResult result; AddressableAssetSettings.BuildPlayerContent(out AddressablesPlayerBuildResult result); bool success = string.IsNullOrEmpty(result.Error); if (!success) { Debug.LogError("Addressables build error encountered: " + result.Error); } }
public override void FixIssues(AddressableAssetSettings settings) { // If we have no duplicate data, run the check again if (duplicateAssetsAndParents == null || duplicateAssetsAndParents.Count == 0) { CheckForDuplicateDependencies(settings); } // If we have found no duplicates, return if (duplicateAssetsAndParents.Count == 0) { return; } // Setup Addressables Group to store all our duplicate assets string desiredGroupName = "Duplicate Assets Sorted By Label"; AddressableAssetGroup group = settings.FindGroup(desiredGroupName); if (group == null) { group = settings.CreateGroup(desiredGroupName, false, false, false, null, typeof(BundledAssetGroupSchema), typeof(ContentUpdateGroupSchema)); var bundleSchema = group.GetSchema <BundledAssetGroupSchema>(); // Set to pack by label so that assets with the same label are put in the same AssetBundle bundleSchema.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackTogetherByLabel; } EditorUtility.DisplayProgressBar("Setting up De-Duplication Group...", "", 0f / duplicateAssetsAndParents.Count); // Iterate through each duplicate asset int bundleNumber = 1; foreach (var entry in duplicateAssetsAndParents) { EditorUtility.DisplayProgressBar("Setting up De-Duplication Group...", "Creating Label Group", ((float)bundleNumber) / duplicateAssetsAndParents.Count); string desiredLabelName = "Bundle" + bundleNumber; List <AddressableAssetEntry> entriesToAdd = new List <AddressableAssetEntry>(); // Put each asset in the shared Group foreach (string assetPath in entry.Value) { entriesToAdd.Add(settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(assetPath).ToString(), group, false, false)); } // Set the label for this selection of assets so they get packed into the same AssetBundle settings.AddLabel(desiredLabelName); SetLabelValueForEntries(settings, entriesToAdd, desiredLabelName, true); bundleNumber++; } settings.SetDirty(AddressableAssetSettings.ModificationEvent.BatchModification, null, true, true); }
static AddressableAssetGroup FindOrCreateGroup(AddressableAssetSettings setting, string gname) { var group = setting.FindGroup(gname); if (group == null) { group = setting.CreateGroup(gname, false, false, false, null, typeof(ContentUpdateGroupSchema), typeof(BundledAssetGroupSchema)); var schema = group.GetSchema <BundledAssetGroupSchema>(); schema.BuildPath.SetVariableByName(setting, "LocalBuildPath"); schema.LoadPath.SetVariableByName(setting, "LocalLoadPath"); schema.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackTogether; } return(group); }
private static void BuildGroup(string groupFolder, AddressableAssetSettings settings, List <AddressableAssetGroupSchema> schemas) { List <string> assetPaths = Directory.EnumerateFiles(groupFolder, "*.*", SearchOption.AllDirectories) .Where(p => Path.GetExtension(p) != ".meta") .Select(p => p.Substring(UnityEngine.Application.dataPath.Length - 6)) .ToList(); if (assetPaths.Count < 1) { return; } string groupName = groupFolder.Substring(groupFolder.LastIndexOf('/') + 1); if (groupName.StartsWith("~") || groupName == "Resources") { return; } AddressableAssetGroup group = settings.FindGroup(groupName); if (group != null) { settings.RemoveGroup(group); } group = settings.CreateGroup(groupName, false, false, true, schemas); foreach (string path in assetPaths) { string address = Path.GetFileNameWithoutExtension(path); if (address.StartsWith("~")) { continue; } if (address == tempAddress) { Log.Info($"Address重复->{address}"); } var enity = settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(path), group); enity.SetAddress(address); enity.SetLabel("default", true); tempAddress = address; } if (groupName == "Default Local Group") { settings.DefaultGroup = group; } }
//创建组 private static AddressableAssetGroup CreateOrGetNonStaticGroup(AddressableAssetSettings settings, string groupName) { var group = settings.FindGroup(groupName); if (group == null) { group = settings.CreateGroup(groupName, false, false, false, null, typeof(BundledAssetGroupSchema), typeof(ContentUpdateGroupSchema)); } group.GetSchema <ContentUpdateGroupSchema>().StaticContent = false; BundledAssetGroupSchema groupSchema = group.GetSchema <BundledAssetGroupSchema>(); //groupSchema.UseAssetBundleCrc = false; //groupSchema.BundleNaming = BundledAssetGroupSchema.BundleNamingStyle.OnlyHash; groupSchema.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackSeparately; groupSchema.BuildPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteBuildPath); groupSchema.BuildPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteLoadPath); return(group); }
private static void GenerateWithGroupRule(AddressableAssetSettings settings, GenerateSetting generateSetting, GroupRule groupRule) { AddressableAssetGroup oldGroup = settings.FindGroup(groupRule.GroupName); AddressableAssetGroup group; if (generateSetting.RecreateGroup) { if (oldGroup) { settings.RemoveGroup(oldGroup); oldGroup = null; } group = settings.CreateGroup(groupRule.GroupName, false, false, true, groupRule.SchemasToCopy); } else { if (oldGroup) { group = oldGroup; } else { group = settings.CreateGroup(groupRule.GroupName, false, false, true, groupRule.SchemasToCopy); } } if (generateSetting.ApplyAssetRule) { for (int iAssetRule = 0; iAssetRule < groupRule.AssetRules.Length; iAssetRule++) { AssetRule iterAssetRule = groupRule.AssetRules[iAssetRule]; GenerateWithAssetRule(settings, generateSetting, group, groupRule, iterAssetRule); } } if (generateSetting.RemoveInvalidAsset) { RemoveInvalidAsset(group); } }
void ImportSchemasInternal(AddressableAssetSettings settings, string groupName, string schemaFolder) { if (string.IsNullOrEmpty(schemaFolder) || !Directory.Exists(schemaFolder)) { Debug.LogError($"Schema folder path is not a valid folder '{schemaFolder}'. Schemas will not be imported."); return; } AddressableAssetGroup group = settings.FindGroup(groupName); if (group == null) { Debug.LogError($"Settings does not contain group '{groupName}'. Schemas will not be imported."); return; } string[] schemaPaths = Directory.GetFiles(schemaFolder); foreach (string unparsedPath in schemaPaths) { if (Path.GetExtension(unparsedPath).ToLower() != ".asset") { continue; } string path = unparsedPath.Replace("\\", "/"); AddressableAssetGroupSchema schema = AssetDatabase.LoadAssetAtPath <AddressableAssetGroupSchema>(path); if (schema == null) { Debug.LogError($"Cannot load schema asset at '{path}'. Schema will not be imported."); continue; } if (schema is BundledAssetGroupSchema bundledSchema) { List <string> variableNames = schema.Group.Settings.profileSettings.GetVariableNames(); SetBundledAssetGroupSchemaPaths(settings, bundledSchema.BuildPath, AddressableAssetSettings.kLocalBuildPath, "LocalBuildPath", variableNames); SetBundledAssetGroupSchemaPaths(settings, bundledSchema.LoadPath, AddressableAssetSettings.kLocalLoadPath, "LocalLoadPath", variableNames); } group.AddSchema(schema); } }
public static void BuildAssetPack() { Init = true; AddressableAssetSettings setting = AddressableAssetSettingsDefaultObject.Settings; AddressableAssetGroup group = setting.FindGroup("AssetGroup"); List <AddressableAssetEntry> temp = group.entries.ToList(); foreach (var item in temp) { setting.RemoveAssetEntry(item.guid); } string[] p = AssetDatabase.GetAllAssetPaths(); for (int i = 0; i < p.Length; i++) { if (CanPack(p[i])) { setting.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(p[i]), group); } } }
internal void CalculateInputDefinitions(AddressableAssetSettings settings) { var group = settings.FindGroup(g => g.Name.Equals(BuildScenesPreprocessor.ScenesAddressablesGroupName)); if (group == null) { return; } if (group.HasSchema <BundledAssetGroupSchema>()) { var schema = group.GetSchema <BundledAssetGroupSchema>(); List <AssetBundleBuild> bundleInputDefinitions = new List <AssetBundleBuild>(); var modeType = Type.GetType("UnityEditor.AddressableAssets.Build.DataBuilders.BuildScriptPackedMode,Unity.Addressables.Editor.dll"); if (modeType != null) { var methodInfo = modeType.GetMethod("PrepGroupBundlePacking", BindingFlags.NonPublic | BindingFlags.Static); if (methodInfo != null) { var entries = (IEnumerable <AddressableAssetEntry>)methodInfo.Invoke(null, new object[] { group, bundleInputDefinitions, schema.BundleMode }); m_assetEntries.AddRange(entries); for (int i = 0; i < bundleInputDefinitions.Count; i++) { if (m_bundleToAssetGroup.ContainsKey(bundleInputDefinitions[i].assetBundleName)) { bundleInputDefinitions[i] = CreateUniqueBundle(bundleInputDefinitions[i]); } m_bundleToAssetGroup.Add(bundleInputDefinitions[i].assetBundleName, schema.Group.Guid); } m_allBundleInputDefs.AddRange(bundleInputDefinitions); } } } }
TResult DoBuild <TResult>(AddressablesDataBuilderInput builderInput, AddressableAssetSettings aaSettings, AddressableAssetsBuildContext aaContext) where TResult : IDataBuilderResult { if (m_AllBundleInputDefinitions.Count > 0) { if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, "Unsaved scenes")); } var buildTarget = builderInput.Target; var buildTargetGroup = builderInput.TargetGroup; var buildParams = new AddressableAssetsBundleBuildParameters(aaSettings, aaContext.bundleToAssetGroup, buildTarget, buildTargetGroup, aaSettings.buildSettings.bundleBuildPath); var builtinShaderBundleName = aaSettings.DefaultGroup.Name.ToLower().Replace(" ", "").Replace('\\', '/').Replace("//", "/") + "_unitybuiltinshaders.bundle"; var buildTasks = RuntimeDataBuildTasks(aaSettings.buildSettings.compileScriptsInVirtualMode, builtinShaderBundleName); ExtractDataTask extractData = new ExtractDataTask(); buildTasks.Add(extractData); string aaPath = aaSettings.AssetPath; IBundleBuildResults results; var exitCode = ContentPipeline.BuildAssetBundles(buildParams, new BundleBuildContent(m_AllBundleInputDefinitions), out results, buildTasks, aaContext); if (exitCode < ReturnCode.Success) { return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, "SBP Error" + exitCode)); } if (aaSettings == null && !string.IsNullOrEmpty(aaPath)) { aaSettings = AssetDatabase.LoadAssetAtPath <AddressableAssetSettings>(aaPath); } } var bundledAssets = new Dictionary <object, HashSet <string> >(); foreach (var loc in aaContext.locations) { if (loc.Dependencies != null && loc.Dependencies.Count > 0) { for (int i = 0; i < loc.Dependencies.Count; i++) { var dep = loc.Dependencies[i]; HashSet <string> assetsInBundle; if (!bundledAssets.TryGetValue(dep, out assetsInBundle)) { bundledAssets.Add(dep, assetsInBundle = new HashSet <string>()); } if (i == 0 && !assetsInBundle.Contains(loc.InternalId)) //only add the asset to the first bundle... { assetsInBundle.Add(loc.InternalId); } } } } foreach (var bd in bundledAssets) { AddressableAssetGroup group = aaSettings.DefaultGroup; string groupGuid; if (aaContext.bundleToAssetGroup.TryGetValue(bd.Key as string, out groupGuid)) { group = aaSettings.FindGroup(g => g.Guid == groupGuid); } var schema = group.GetSchema <BundledAssetGroupSchema>(); if (schema != null) { var bundleLocData = aaContext.locations.First(s => s.Keys[0] == bd.Key); var isLocalBundle = IsInternalIdLocal(bundleLocData.InternalId); uint crc = (uint)UnityEngine.Random.Range(0, int.MaxValue); var hash = Guid.NewGuid().ToString(); string originalBundleName = bd.Key as string; string newBundleName = BuildUtility.GetNameWithHashNaming(schema.BundleNaming, hash, originalBundleName); bundleLocData.InternalId = bundleLocData.InternalId.Remove(bundleLocData.InternalId.Length - originalBundleName.Length) + newBundleName; var virtualBundleName = AddressablesRuntimeProperties.EvaluateString(bundleLocData.InternalId); var bundleData = new VirtualAssetBundle(virtualBundleName, isLocalBundle, crc, hash); long dataSize = 0; long headerSize = 0; foreach (var a in bd.Value) { var size = ComputeSize(a); bundleData.Assets.Add(new VirtualAssetBundleEntry(a, size)); dataSize += size; headerSize += a.Length * 5; //assume 5x path length overhead size per item, probably much less } if (bd.Value.Count == 0) { dataSize = 100 * 1024; headerSize = 1024; } bundleData.SetSize(dataSize, headerSize); var requestOptions = new VirtualAssetBundleRequestOptions { Crc = schema.UseAssetBundleCrc ? crc : 0, Hash = schema.UseAssetBundleCache ? hash : "", ChunkedTransfer = schema.ChunkedTransfer, RedirectLimit = schema.RedirectLimit, RetryCount = schema.RetryCount, Timeout = schema.Timeout, BundleName = Path.GetFileName(bundleLocData.InternalId), BundleSize = dataSize + headerSize }; bundleLocData.Data = requestOptions; var bundleProviderId = schema.GetBundleCachedProviderId(); var virtualBundleRuntimeData = m_CreatedProviderIds[bundleProviderId]; virtualBundleRuntimeData.AssetBundles.Add(bundleData); } } foreach (var kvp in m_CreatedProviderIds) { if (kvp.Value != null) { var bundleProviderData = ObjectInitializationData.CreateSerializedInitializationData <VirtualAssetBundleProvider>(kvp.Key, kvp.Value); m_ResourceProviderData.Add(bundleProviderData); } } var contentCatalog = new ContentCatalogData(aaContext.locations, ResourceManagerRuntimeData.kCatalogAddress); contentCatalog.ResourceProviderData.AddRange(m_ResourceProviderData); foreach (var t in aaContext.providerTypes) { contentCatalog.ResourceProviderData.Add(ObjectInitializationData.CreateSerializedInitializationData(t)); } contentCatalog.InstanceProviderData = ObjectInitializationData.CreateSerializedInitializationData(instanceProviderType.Value); contentCatalog.SceneProviderData = ObjectInitializationData.CreateSerializedInitializationData(sceneProviderType.Value); //save catalog WriteFile(string.Format(m_PathFormat, "", "catalog"), JsonUtility.ToJson(contentCatalog), builderInput.Registry); foreach (var io in aaSettings.InitializationObjects) { if (io is IObjectInitializationDataProvider) { aaContext.runtimeData.InitializationObjects.Add((io as IObjectInitializationDataProvider).CreateObjectInitializationData()); } } var settingsPath = string.Format(m_PathFormat, "", "settings"); WriteFile(settingsPath, JsonUtility.ToJson(aaContext.runtimeData), builderInput.Registry); //inform runtime of the init data path var runtimeSettingsPath = string.Format(m_PathFormat, "file://{UnityEngine.Application.dataPath}/../", "settings"); PlayerPrefs.SetString(Addressables.kAddressablesRuntimeDataPath, runtimeSettingsPath); var result = AddressableAssetBuildResult.CreateResult <TResult>(settingsPath, aaContext.locations.Count); return(result); }
internal static ReturnCode RunInternal(IAddressableAssetsBuildContext aaBuildContext, IBundleWriteData writeData, IDependencyData dependencyData) { var aaContext = aaBuildContext as AddressableAssetsBuildContext; if (aaContext == null) { return(ReturnCode.Error); } AddressableAssetSettings aaSettings = aaContext.Settings; List <ContentCatalogDataEntry> locations = aaContext.locations; Dictionary <string, string> bundleToAssetGroup = aaContext.bundleToAssetGroup; var bundleToAssets = new Dictionary <string, List <GUID> >(); var dependencySetForBundle = new Dictionary <string, HashSet <string> >(); foreach (KeyValuePair <GUID, List <string> > k in writeData.AssetToFiles) { List <GUID> assetList; string bundle = writeData.FileToBundle[k.Value[0]]; if (!bundleToAssets.TryGetValue(bundle, out assetList)) { bundleToAssets.Add(bundle, assetList = new List <GUID>()); } HashSet <string> bundleDeps; if (!dependencySetForBundle.TryGetValue(bundle, out bundleDeps)) { dependencySetForBundle.Add(bundle, bundleDeps = new HashSet <string>()); } for (int i = 0; i < k.Value.Count; i++) { bundleDeps.Add(writeData.FileToBundle[k.Value[i]]); } foreach (string file in k.Value) { string fileBundle = writeData.FileToBundle[file]; if (!bundleToAssets.ContainsKey(fileBundle)) { bundleToAssets.Add(fileBundle, new List <GUID>()); } } assetList.Add(k.Key); } var assetGroupToBundle = (aaContext.assetGroupToBundles = new Dictionary <AddressableAssetGroup, List <string> >()); foreach (KeyValuePair <string, List <GUID> > kvp in bundleToAssets) { AddressableAssetGroup assetGroup = aaSettings.DefaultGroup; string groupGuid; if (bundleToAssetGroup.TryGetValue(kvp.Key, out groupGuid)) { assetGroup = aaSettings.FindGroup(g => g != null && g.Guid == groupGuid); } List <string> bundles; if (!assetGroupToBundle.TryGetValue(assetGroup, out bundles)) { assetGroupToBundle.Add(assetGroup, bundles = new List <string>()); } bundles.Add(kvp.Key); HashSet <string> bundleDeps = null; dependencySetForBundle.TryGetValue(kvp.Key, out bundleDeps); CreateResourceLocationData(assetGroup, kvp.Key, GetLoadPath(assetGroup, kvp.Key), GetBundleProviderName(assetGroup), GetAssetProviderName(assetGroup), kvp.Value, bundleDeps, locations, aaContext.providerTypes, dependencyData); } return(ReturnCode.Success); }
public override List <AnalyzeResult> RefreshAnalysis(AddressableAssetSettings settings) { List <AnalyzeResult> results = new List <AnalyzeResult>(); ClearAnalysis(); ClearOurData(); if (!BuildUtility.CheckModifiedScenesAndAskToSave()) { Debug.LogError("Cannot run Analyze with unsaved scenes"); results.Add(new AnalyzeResult { resultName = ruleName + "Cannot run Analyze with unsaved scenes" }); return(results); } // Get all folders in Assets/AutoBundles HashSet <string> folderNames = new HashSet <string>(); var folders = AssetDatabase.GetSubFolders("Assets/" + autoBundlesFolderName); foreach (var folder in folders) { folderNames.Add(Path.GetFileName(folder)); } // Get all addressable groups carrying the (Auto) prefix HashSet <string> autoGroups = new HashSet <string>(); foreach (var group in settings.groups) { if (group.name.StartsWith(autoGroupPrefix)) { autoGroups.Add(group.name); } } // Collect all groups that must be created or moved foreach (var folder in folderNames) { var autoName = autoGroupPrefix + folder; if (!autoGroups.Contains(autoName)) { groupsToCreate.Add(autoName); results.Add(new AnalyzeResult() { resultName = "Create group \"" + autoName + "\"" }); } } // Collect all groups that must be removed foreach (var groupName in autoGroups) { var baseName = groupName.Substring(autoGroupPrefix.Length); if (!folderNames.Contains(baseName)) { groupsToRemove.Add(groupName); results.Add(new AnalyzeResult() { resultName = "Remove group \"" + groupName + "\"" }); } } // Collect all assets that have zero or one references. They will not be bundled, because // Addressables will automatically bring them in. This reduces the number of individual bundles. Dictionary <string, int> refCounts = new Dictionary <string, int>(); var guids = AssetDatabase.FindAssets(assetFilter, new [] { "Assets" }); foreach (var guid in guids) { string path = AssetDatabase.GUIDToAssetPath(guid); var dependencies = AssetDatabase.GetDependencies(path); foreach (var asset in dependencies) { if (asset == path) { // Ignore self continue; } if (refCounts.ContainsKey(asset)) { refCounts[asset]++; } else { refCounts[asset] = 1; } } } // Select which items to never bundle. This includes items that have no references or only one references, // as well as unwanted file extensions. HashSet <string> neverBundle = new HashSet <string>(); foreach (KeyValuePair <string, int> asset in refCounts) { if (asset.Value == 0 && neverBundleNoReferences || asset.Value == 1) { neverBundle.Add(asset.Key); break; } bool ignore = false; foreach (var ext in ignoreExtensions) { if (asset.Key.ToLower().EndsWith(ext)) { ignore = true; break; } } if (ignore) { neverBundle.Add(asset.Key); } } // Collect all assets to create as addressables string preamble = "Assets/" + autoBundlesFolderName + "/"; foreach (var folder in folderNames) { var assetGuids = AssetDatabase.FindAssets(assetFilter, new [] { "Assets/" + autoBundlesFolderName + "/" + folder }); // Schedule creation/moving of assets that exist foreach (var guid in assetGuids) { var addrPath = AssetDatabase.GUIDToAssetPath(guid); // Skip assets we're never bundling if (neverBundle.Contains(addrPath)) { continue; } // Remove the Assets/AutoBundles/ part of assets paths. if (addrPath.StartsWith(preamble)) { addrPath = addrPath.Substring(preamble.Length); } // Create asset creation/moving action. string autoGroup = autoGroupPrefix + folder; assetActions.Add(new AssetAction() { create = true, inGroup = autoGroup, assetGuid = guid, addressablePath = addrPath }); AddressableAssetEntry entry = settings.FindAssetEntry(guid); if (entry == null) { results.Add(new AnalyzeResult() { resultName = "Add:" + addrPath }); } else { results.Add(new AnalyzeResult() { resultName = "Keep or move:" + addrPath }); } } // Schedule removal of assets that exist as addressables but don't exist anywhere under the AutoBundles tree string autoName = autoGroupPrefix + folder; var group = settings.FindGroup(autoName); if (group != null) { List <AddressableAssetEntry> result = new List <AddressableAssetEntry>(); group.GatherAllAssets(result, true, true, true); foreach (var entry in result) { if (entry.IsSubAsset) { continue; } if (entry.guid == "") { Debug.Log("Entry has no guid! " + entry.address); } string assetPath = AssetDatabase.GUIDToAssetPath(entry.guid); if (!assetPath.StartsWith("Assets/" + autoBundlesFolderName + "/")) { assetActions.Add(new AssetAction() { create = false, inGroup = autoName, assetGuid = entry.guid, addressablePath = entry.address, }); // Print removal message without preamble results.Add(new AnalyzeResult() { resultName = "Remove:" + entry.address }); } } } } return(results); }
public override List <AnalyzeResult> RefreshAnalysis(AddressableAssetSettings settings) { List <AnalyzeResult> results = new List <AnalyzeResult>(); ClearAnalysis(); ClearOurData(); var projectRoot = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets/".Length); if (!BuildUtility.CheckModifiedScenesAndAskToSave()) { Debug.LogError("Cannot run Analyze with unsaved scenes"); results.Add(new AnalyzeResult { resultName = ruleName + "Cannot run Analyze with unsaved scenes" }); return(results); } // Get all immediate folders in Assets/AutoBundles HashSet <string> folderNames = new HashSet <string>(); var folders = AssetDatabase.GetSubFolders("Assets/" + autoBundlesFolderName); foreach (var folder in folders) { folderNames.Add(Path.GetFileName(folder)); } // Get all addressable groups carrying the (Auto) prefix HashSet <string> autoGroups = new HashSet <string>(); foreach (var group in settings.groups) { if (group.name.StartsWith(autoGroupPrefix)) { autoGroups.Add(group.name); } } // Collect all groups that must be created or moved foreach (var folder in folderNames) { var autoName = autoGroupPrefix + folder; if (!autoGroups.Contains(autoName)) { groupsToCreate.Add(autoName); results.Add(new AnalyzeResult() { resultName = "Create group \"" + autoName + "\"" }); } } // Collect all groups that must be removed foreach (var groupName in autoGroups) { var baseName = groupName.Substring(autoGroupPrefix.Length); if (!folderNames.Contains(baseName)) { groupsToRemove.Add(groupName); results.Add(new AnalyzeResult() { resultName = "Remove group \"" + groupName + "\"" }); } } // Get all assets var allGuids = AssetDatabase.FindAssets(assetFilter, new [] { "Assets/" + autoBundlesFolderName }); var neverBundle = new HashSet <string>(); // Only include assets that pass basic filtering, like file extension. // Result is "assetPaths", the authoritative list of assets we're considering bundling. var assetPaths = new HashSet <string>(); foreach (var guid in allGuids) { var path = AssetDatabase.GUIDToAssetPath(guid); if (ShouldIgnoreAsset(path)) { neverBundle.Add(path.ToLower()); } else { assetPaths.Add(path); } } // Collect all parents of all assets in preparation for not bundling assets with one ultimate non-scene parent. var parents = new Dictionary <string, HashSet <string> >(); // Map from asset guid to all its parents foreach (var path in assetPaths) { var dependencies = AssetDatabase.GetDependencies(path); foreach (var asset in dependencies) { if (asset == path) { // Ignore self continue; } if (ShouldIgnoreAsset(asset)) { continue; } if (!parents.ContainsKey(asset)) { parents.Add(asset, new HashSet <string>()); } parents[asset].Add(path); } } // Unbundle assets with zero parents foreach (var asset in assetPaths) { if (!parents.ContainsKey(asset)) { neverBundle.Add(asset.ToLower()); } } Debug.Log(neverBundle.Count + " asset have zero parents and won't be bundled"); int floor = neverBundle.Count; // Unbundle assets with one parent foreach (var asset in assetPaths) { if (parents.ContainsKey(asset) && parents[asset].Count == 1) { neverBundle.Add(asset.ToLower()); } } Debug.Log((neverBundle.Count - floor) + " asset have one parent and won't be bundled"); floor = neverBundle.Count; // Unbundle assets with one ultimate parent var ultimateParents = new Dictionary <string, HashSet <string> >(); foreach (var asset in assetPaths) { if (neverBundle.Contains(asset.ToLower())) { continue; } ultimateParents[asset] = new HashSet <string>(); // Iterate all the way to the top for this asset. Assemble a list of all ultimate parents of this asset. var parentsToCheck = new List <string>(); parentsToCheck.AddRange(parents[asset].ToList()); while (parentsToCheck.Count != 0) { var checking = parentsToCheck[0]; parentsToCheck.RemoveAt(0); if (!parents.ContainsKey(checking)) { // If asset we're checking doesn't itself have any parents, this is the end. ultimateParents[asset].Add(checking); } else { parentsToCheck.AddRange(parents[checking]); } } } // Unbundle all assets that don't have two or more required objects as ultimate parents. // Objects with one included parent will still get included if needed, just not as a separate Addressable. foreach (KeyValuePair <string, HashSet <string> > pair in ultimateParents) { int requiredParents = 0; foreach (var ultiParent in pair.Value) { if (AlwaysIncludeAsset(ultiParent)) { requiredParents++; } } if (requiredParents <= 1) { neverBundle.Add(pair.Key.ToLower()); } } Debug.Log((neverBundle.Count - floor) + " asset have zero or one ultimate parents and won't be bundled"); floor = neverBundle.Count; // Skip assets that are too small. This is a tradeoff between individual access to files, // versus the game not having an open file handle for every single 2 KB thing. We're choosing // to duplicate some things by baking them into multiple bundles, even though it requires // more storage and bandwidth. int tooSmallCount = 0; foreach (var asset in assetPaths) { if (neverBundle.Contains(asset.ToLower())) { continue; } var diskPath = projectRoot + "/" + asset; var fileInfo = new System.IO.FileInfo(diskPath); if (fileInfo.Length < 10000) { tooSmallCount++; neverBundle.Add(asset.ToLower()); } } Debug.Log(tooSmallCount + " assets are too small and won't be bundled"); // Collect all assets to create as addressables string preamble = "Assets/" + autoBundlesFolderName + "/"; var expresslyBundled = new HashSet <string>(); foreach (var folder in folderNames) { var assetGuids = AssetDatabase.FindAssets(assetFilter, new [] { "Assets/" + autoBundlesFolderName + "/" + folder }); // Schedule creation/moving of assets that exist foreach (var guid in assetGuids) { var addrPath = AssetDatabase.GUIDToAssetPath(guid); // Skip assets we're never bundling string lowerPath = addrPath.ToLower(); if (neverBundle.Contains(lowerPath) && !AlwaysIncludeAsset(lowerPath)) { continue; } // Remove the Assets/AutoBundles/ part of assets paths. var shortPath = addrPath; if (shortPath.StartsWith(preamble)) { shortPath = shortPath.Substring(preamble.Length); } // Create asset creation/moving action. string autoGroup = autoGroupPrefix + folder; assetActions.Add(new AssetAction() { create = true, inGroup = autoGroup, assetGuid = guid, addressablePath = shortPath }); AddressableAssetEntry entry = settings.FindAssetEntry(guid); if (entry == null) { results.Add(new AnalyzeResult() { resultName = "Add:" + shortPath }); } else { results.Add(new AnalyzeResult() { resultName = "Keep or move:" + shortPath }); } expresslyBundled.Add(shortPath); } } // Schedule removal of assets in auto folders that exist as addressables but aren't expressly bundled. foreach (var folder in folderNames) { string autoName = autoGroupPrefix + folder; var group = settings.FindGroup(autoName); if (group != null) { List <AddressableAssetEntry> result = new List <AddressableAssetEntry>(); group.GatherAllAssets(result, true, false, true); foreach (var entry in result) { if (entry.IsSubAsset) { continue; } if (entry.guid == "") { Debug.Log("Entry has no guid! " + entry.address); } if (!expresslyBundled.Contains(entry.address)) { assetActions.Add(new AssetAction() { create = false, inGroup = autoName, assetGuid = entry.guid, addressablePath = entry.address, }); // Print removal message without preamble results.Add(new AnalyzeResult() { resultName = "Remove:" + entry.address }); } } } } return(results); }