using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Serialization;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.ResourceManagement.Util;
using UnityEngine.SceneManagement;
using System.Collections;
using System.Text;
using UnityEngine.Networking;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.AddressableAssets
{
///
/// A container for data pertaining to a specific Resource Locator. Used mainly to determine if a content catalog
/// needs to be updated.
///
public class ResourceLocatorInfo
{
///
/// The Resource Locator that has been loaded into the Addressables system.
///
public IResourceLocator Locator { get; private set; }
///
/// The local hash for this Resource Locator. If a remote content catalog is updated and the remote hash changes,
/// this locator info is used to determine if a new content catalog needs to be updated.
///
public string LocalHash { get; private set; }
///
/// The Content Catalog location this Resource Locator was loaded from. Catalog locations typically contain
/// exactly two dependencies. The first dependency is the remote location of the content catalog hash file, the
/// second is the local path of the hash file.
///
public IResourceLocation CatalogLocation { get; private set; }
internal bool ContentUpdateAvailable { get; set; }
///
/// Contstruct a ResourceLocatorInfo for a given Resource Locator.
///
/// The IResourceLocator to track.
/// The local hash of the content catalog.
/// The location for the remote catalog. Typically this location contains exactly two dependeices,
/// the first one pointing to the remote hash file. The second dependency pointing to the local hash file.
public ResourceLocatorInfo(IResourceLocator loc, string localHash, IResourceLocation remoteCatalogLocation)
{
Locator = loc;
LocalHash = localHash;
CatalogLocation = remoteCatalogLocation;
}
///
/// The remote hash location of the content catalog used by the resource locator
///
public IResourceLocation HashLocation
{
get { return CatalogLocation.Dependencies[0]; }
}
///
/// Checks to see if the provided CatalogLocation contains the expected amount of dependencies to check for catalog updates
///
public bool CanUpdateContent
{
get { return !string.IsNullOrEmpty(LocalHash) && CatalogLocation != null && CatalogLocation.HasDependencies && CatalogLocation.Dependencies.Count == 2; }
}
internal void UpdateContent(IResourceLocator locator, string hash, IResourceLocation loc)
{
LocalHash = hash;
CatalogLocation = loc;
Locator = locator;
}
}
///
/// Exception to encapsulate invalid key errors.
///
public class InvalidKeyException : Exception
{
///
/// The key used to generate the exception.
///
public object Key { get; private set; }
///
/// The type of the key used to generate the exception.
///
public Type Type { get; private set; }
///
/// MergeMode if used, else null.
///
public Addressables.MergeMode? MergeMode { get; }
///
/// Construct a new InvalidKeyException.
///
/// The key that caused the exception.
public InvalidKeyException(object key) : this(key, typeof(object))
{
}
private AddressablesImpl m_Addressables;
///
/// Construct a new InvalidKeyException.
///
/// The key that caused the exception.
/// The type of the key that caused the exception.
public InvalidKeyException(object key, Type type)
{
Key = key;
Type = type;
}
internal InvalidKeyException(object key, Type type, AddressablesImpl addr)
{
Key = key;
Type = type;
m_Addressables = addr;
}
///
/// Construct a new InvalidKeyException.
///
/// The key that caused the exception.
/// The type of the key that caused the exception.
/// The mergeMode of the input that caused the exception.
public InvalidKeyException(object key, Type type, Addressables.MergeMode mergeMode)
{
Key = key;
Type = type;
MergeMode = mergeMode;
}
internal InvalidKeyException(object key, Type type, Addressables.MergeMode mergeMode, AddressablesImpl addr)
{
Key = key;
Type = type;
MergeMode = mergeMode;
m_Addressables = addr;
}
///
public InvalidKeyException()
{
}
///
public InvalidKeyException(string message) : base(message)
{
}
///
public InvalidKeyException(string message, Exception innerException) : base(message, innerException)
{
}
///
protected InvalidKeyException(SerializationInfo message, StreamingContext context) : base(message, context)
{
}
const string BaseInvalidKeyMessageFormat = "{0}, Key={1}, Type={2}";
///
/// Stores information about the exception.
///
public override string Message
{
get
{
string stringKey = Key as string;
if (!string.IsNullOrEmpty(stringKey))
{
if (m_Addressables == null)
return string.Format(BaseInvalidKeyMessageFormat, base.Message, stringKey, Type);
return GetMessageForSingleKey(stringKey);
}
IEnumerable enumerableKey = Key as IEnumerable;
if (enumerableKey != null)
{
int keyCount = 0;
List stringKeys = new List();
HashSet keyTypeNames = new HashSet();
foreach (object keyObj in enumerableKey)
{
keyCount++;
keyTypeNames.Add(keyObj.GetType().ToString());
if (keyObj is string)
stringKeys.Add(keyObj as string);
}
if (!MergeMode.HasValue)
{
string keysCSV = GetCSVString(stringKeys, "Key=", "Keys=");
return $"{base.Message} No MergeMode is set to merge the multiple keys requested. {keysCSV}, Type={Type}";
}
if (keyCount != stringKeys.Count)
{
string types = GetCSVString(keyTypeNames, "Type=", "Types=");
return $"{base.Message} Enumerable key contains multiple Types. {types}, all Keys are expected to be strings";
}
if (keyCount == 1)
return GetMessageForSingleKey(stringKeys[0]);
return GetMessageforMergeKeys(stringKeys);
}
return string.Format(BaseInvalidKeyMessageFormat, base.Message, Key, Type);
}
}
string GetMessageForSingleKey(string keyString)
{
#if UNITY_EDITOR
string path = AssetDatabase.GUIDToAssetPath(keyString);
if (!string.IsNullOrEmpty(path))
{
Type directType = AssetDatabase.GetMainAssetTypeAtPath(path);
if (directType != null)
return $"{base.Message} Could not load Asset with GUID={keyString}, Path={path}. Asset exists with main Type={directType}, which is not assignable from the requested Type={Type}";
return string.Format(BaseInvalidKeyMessageFormat, base.Message, keyString, Type);
}
#endif
HashSet typesAvailableForKey = GetTypesForKey(keyString);
if (typesAvailableForKey.Count == 0)
return $"{base.Message} No Location found for Key={keyString}";
if (typesAvailableForKey.Count == 1)
{
Type availableType = null;
foreach (Type type in typesAvailableForKey)
availableType = type;
if (availableType == null)
return string.Format(BaseInvalidKeyMessageFormat, base.Message, keyString, Type);
return $"{base.Message} No Asset found with for Key={keyString}. Key exists as Type={availableType}, which is not assignable from the requested Type={Type}";
}
StringBuilder csv = new StringBuilder(512);
int count = 0;
foreach (Type type in typesAvailableForKey)
{
count++;
csv.Append(count > 1 ? $", {type}" : type.ToString());
}
return $"{base.Message} No Asset found with for Key={keyString}. Key exists as multiple Types={csv}, which is not assignable from the requested Type={Type}";
}
string GetMessageforMergeKeys(List keys)
{
string keysCSV = GetCSVString(keys, "Key=", "Keys=");
string NoLocationLineMessage = "\nNo Location found for Key={0}";
StringBuilder messageBuilder = null;
switch (MergeMode)
{
case Addressables.MergeMode.Union:
{
messageBuilder = new StringBuilder($"{base.Message} No {MergeMode.Value} of Assets between {keysCSV} with Type={Type}");
Dictionary> typeToKeys = new Dictionary>();
foreach (string key in keys)
{
if (!GetTypeToKeys(key, typeToKeys))
messageBuilder.Append(string.Format(NoLocationLineMessage, key));
}
foreach (KeyValuePair> pair in typeToKeys)
{
string availableKeysString = GetCSVString(pair.Value, "Key=", "Keys=");
List unavailableKeys = new List();
foreach (string key in keys)
{
if (!pair.Value.Contains(key))
unavailableKeys.Add(key);
}
if (unavailableKeys.Count == 0)
messageBuilder.Append($"\nUnion of Type={pair.Key} found with {availableKeysString}");
else
{
string unavailableKeysString = GetCSVString(unavailableKeys, "Key=", "Keys=");
messageBuilder.Append($"\nUnion of Type={pair.Key} found with {availableKeysString}. Without {unavailableKeysString}");
}
}
}
break;
case Addressables.MergeMode.Intersection:
{
messageBuilder = new StringBuilder($"{base.Message} No {MergeMode.Value} of Assets between {keysCSV} with Type={Type}");
bool hasInvalidKeys = false;
Dictionary> typeToKeys = new Dictionary>();
foreach (string key in keys)
{
if (!GetTypeToKeys(key, typeToKeys))
{
hasInvalidKeys = true;
messageBuilder.Append(string.Format(NoLocationLineMessage, key));
}
}
if (hasInvalidKeys)
break;
foreach (KeyValuePair> pair in typeToKeys)
{
if (pair.Value.Count == keys.Count)
messageBuilder.Append($"\nAn Intersection exists for Type={pair.Key}");
}
}
break;
case Addressables.MergeMode.UseFirst:
{
messageBuilder = new StringBuilder($"{base.Message} No {MergeMode.Value} Asset within {keysCSV} with Type={Type}");
Dictionary> typeToKeys = new Dictionary>();
foreach (string key in keys)
{
if (!GetTypeToKeys(key, typeToKeys))
messageBuilder.Append(string.Format(NoLocationLineMessage, key));
}
string keyCSV;
foreach (KeyValuePair> pair in typeToKeys)
{
keyCSV = GetCSVString(pair.Value, "Key=", "Keys=");
messageBuilder.Append($"\nType={pair.Key} exists for {keyCSV}");
}
}
break;
}
return messageBuilder.ToString();
}
HashSet GetTypesForKey(string keyString)
{
HashSet typesAvailableForKey = new HashSet();
foreach (var locator in m_Addressables.ResourceLocators)
{
if (!locator.Locate(keyString, null, out var locations))
continue;
foreach (IResourceLocation location in locations)
typesAvailableForKey.Add(location.ResourceType);
}
return typesAvailableForKey;
}
bool GetTypeToKeys(string key, Dictionary> typeToKeys)
{
HashSet types = GetTypesForKey(key);
if (types.Count == 0)
return false;
foreach (Type type in types)
{
if (!typeToKeys.TryGetValue(type, out List keysForType))
typeToKeys.Add(type, new List() {key});
else
keysForType.Add(key);
}
return true;
}
string GetCSVString(IEnumerable enumerator, string prefixSingle, string prefixPlural)
{
StringBuilder keysCSVBuilder = new StringBuilder(prefixPlural);
int count = 0;
foreach (var key in enumerator)
{
count++;
keysCSVBuilder.Append(count > 1 ? $", {key}" : key);
}
if (count == 1 && !string.IsNullOrEmpty(prefixPlural) && !string.IsNullOrEmpty(prefixSingle))
keysCSVBuilder.Replace(prefixPlural, prefixSingle);
return keysCSVBuilder.ToString();
}
}
///
/// Entry point for Addressable API, this provides a simpler interface than using ResourceManager directly as it assumes string address type.
///
public static class Addressables
{
internal static bool reinitializeAddressables = true;
internal static AddressablesImpl m_AddressablesInstance = new AddressablesImpl(new LRUCacheAllocationStrategy(1000, 1000, 100, 10));
static AddressablesImpl m_Addressables
{
get
{
#if UNITY_EDITOR
if (EditorSettings.enterPlayModeOptionsEnabled && reinitializeAddressables)
{
reinitializeAddressables = false;
m_AddressablesInstance.ReleaseSceneManagerOperation();
m_AddressablesInstance = new AddressablesImpl(new LRUCacheAllocationStrategy(1000, 1000, 100, 10));
}
#endif
return m_AddressablesInstance;
}
}
///
/// Stores the ResourceManager associated with this Addressables instance.
///
public static ResourceManager ResourceManager
{
get { return m_Addressables.ResourceManager; }
}
internal static AddressablesImpl Instance
{
get { return m_Addressables; }
}
#if UNITY_EDITOR
[InitializeOnLoadMethod]
static void RegisterPlayModeStateChange()
{
EditorApplication.playModeStateChanged += SetAddressablesReInitFlagOnExitPlayMode;
}
static void SetAddressablesReInitFlagOnExitPlayMode(PlayModeStateChange change)
{
if (change == PlayModeStateChange.EnteredEditMode || change == PlayModeStateChange.ExitingPlayMode)
reinitializeAddressables = true;
}
#endif
///
/// The Instance Provider used by the Addressables System.
///
///
/// Retrieves the interface used by the Addressables Asset System to create instances of Addressable GameObjects.
///
/// The [IInstanceProvider](xref:UnityEngine.ResourceManagement.ResourceProviders.IInstanceProvider) object used to create instances of GameObjects.
///
/// The example below instantiates a GameObject using ProvideInstance.
///
///
public static IInstanceProvider InstanceProvider
{
get { return m_Addressables.InstanceProvider; }
}
///
/// Used to resolve a string using addressables config values
///
/// The internal id to resolve.
/// Returns the string that the internal id represents.
public static string ResolveInternalId(string id)
{
return m_Addressables.ResolveInternalId(id);
}
///
static public Func InternalIdTransformFunc
{
get { return m_Addressables.InternalIdTransformFunc; }
set { m_Addressables.InternalIdTransformFunc = value; }
}
///
public static Action WebRequestOverride
{
get { return m_Addressables.WebRequestOverride; }
set { m_Addressables.WebRequestOverride = value; }
}
///
/// Options for merging the results of requests.
/// If keys (A, B) mapped to results ([1,2,4],[3,4,5])...
/// - UseFirst (or None) takes the results from the first key
/// -- [1,2,4]
/// - Union takes results of each key and collects items that matched any key.
/// -- [1,2,3,4,5]
/// - Intersection takes results of each key, and collects items that matched every key.
/// -- [4]
///
public enum MergeMode
{
///
/// Use to indicate that no merge should occur. The first set of results will be used.
///
None = 0,
///
/// Use to indicate that the merge should take the first set of results.
///
UseFirst = 0,
///
/// Use to indicate that the merge should take the union of the results.
///
Union,
///
/// Use to indicate that the merge should take the intersection of the results.
///
Intersection
}
///
/// The name of the PlayerPrefs value used to set the path to load the addressables runtime data file.
///
public const string kAddressablesRuntimeDataPath = "AddressablesRuntimeDataPath";
const string k_AddressablesLogConditional = "ADDRESSABLES_LOG_ALL";
///
/// The name of the PlayerPrefs value used to set the path to check for build logs that need to be shown in the runtime.
///
public const string kAddressablesRuntimeBuildLogPath = "AddressablesRuntimeBuildLog";
///
/// The subfolder used by the Addressables system for its built data.
///
///
/// The Addressables system currently builds inside the library in a folder named 'aa'. Each platform that is built
/// will be built inside a subfolder matching the platform name. This subfolder is also the base for loading
/// streaming data at runtime. The Editor build location is and player is .
///
///
/// The example demonstrates a utility function that looks inside the Streaming Assets subfolder and gets a list of
/// all the subfolders. This is returned as a list of all platforms that have been built on the current machine.
///
///
public static string StreamingAssetsSubFolder
{
get { return m_Addressables.StreamingAssetsSubFolder; }
}
///
/// The path to the Addressables Library subfolder
///
public static string LibraryPath = "Library/com.unity.addressables/";
///
/// The path to the Addressables Build Reports subfolder
///
public static string BuildReportPath = "Library/com.unity.addressables/BuildReports/";
///
/// The build path used by the Addressables system for its initialization data.
///
///
/// Addressables.BuildPath returns the path used by the Addressables system for its built initialization data.
/// This path is to the Addressables folder in the Project Library folder for the active platform.This folder
/// contains the settings, local catalog and addressables managed local asset bundles.
///
///
/// Gets the runtime settings from the buildPath and returns the Addressables package version that the content was built using.
///
///
///
/// In this example we add a build pre-process hook. When building a player this throws an exception if the content has not been built.
/// This could be useful when 'Build Addressables on Player Build' is not set in Addressables Settings.
///
///
public static string BuildPath
{
get { return m_Addressables.BuildPath; }
}
///
/// The path that addressables player data gets copied to during a player build.
///
///
/// This resolves to Assets/StreamingAssets/aa by default. Files in this folder are included
/// in the player build process. Remote bundles should be built outside this folder to prevent
/// them from being included in the default player build.
///
///
/// This example is a custom build script that extends the default packed build script. Files are built
/// in a custom build folder, and then copied into PlayerBuildDataPath so they are included with
/// the player build.
///
///
public static string PlayerBuildDataPath
{
get { return m_Addressables.PlayerBuildDataPath; }
}
///
/// The path used by the Addressables system to load initialization data.
///
/// ///
/// When running in the Editor Addressables.RuntimePath returns the path to the locally built data in the .
/// When running in a player this returns the path to the same content found in .
/// This folder contains the settings, local catalog and Addressables managed local asset bundles.
///
public static string RuntimePath
{
get { return m_Addressables.RuntimePath; }
}
///
/// Gets the collection of configured objects. Resource Locators are used to find objects from user-defined typed keys.
///
/// The resource locators collection.
public static IEnumerable ResourceLocators
{
get { return m_Addressables.ResourceLocators; }
}
[Conditional(k_AddressablesLogConditional)]
internal static void InternalSafeSerializationLog(string msg, LogType logType = LogType.Log)
{
if (m_AddressablesInstance == null)
return;
switch (logType)
{
case LogType.Warning:
m_AddressablesInstance.LogWarning(msg);
break;
case LogType.Error:
m_AddressablesInstance.LogError(msg);
break;
case LogType.Log:
m_AddressablesInstance.Log(msg);
break;
}
}
[Conditional(k_AddressablesLogConditional)]
internal static void InternalSafeSerializationLogFormat(string format, LogType logType = LogType.Log, params object[] args)
{
if (m_AddressablesInstance == null)
return;
switch (logType)
{
case LogType.Warning:
m_AddressablesInstance.LogWarningFormat(format, args);
break;
case LogType.Error:
m_AddressablesInstance.LogErrorFormat(format, args);
break;
case LogType.Log:
m_AddressablesInstance.LogFormat(format, args);
break;
}
}
///
/// Log can be used to write a Debug level log message.
///
///
/// Log works the same as Debug.Log. Addressables only logs warnings and errors so by default this function does not log anything.
///
/// The msg to log
///
///
///
/// Enable all logging
[Conditional(k_AddressablesLogConditional)]
public static void Log(string msg)
{
m_Addressables.Log(msg);
}
///
/// LogFormat can be used to write a formatted log message.
///
///
/// LogFormat supports Composite Formatting and works the same way as [Debug.LogFormat](xref:UnityEngine.Debug.LogFormat(System.String,System.Object[])). Addressables logs warnings and errors so by default this function will **not** log.
///
/// Enable all logging
/// The string with format tags.
/// The args used to fill in the format tags.
///
///
///
[Conditional(k_AddressablesLogConditional)]
public static void LogFormat(string format, params object[] args)
{
m_Addressables.LogFormat(format, args);
}
///
/// LogWarning can be used to write a log message.
///
///
/// LogWarning works the same way as [Debug.LogWarning](xref:UnityEngine.Debug.LogWarning(System.Object)). Addressables logs warnings and errors so by default this function will log.
///
/// The msg to log
///
///
///
public static void LogWarning(string msg)
{
m_Addressables.LogWarning(msg);
}
///
/// LogFormat can be used to write a formatted log message.
///
///
/// LogWarningFormat supports Composite Formatting and works the same way as [Debug.LogWarningFormat](xref:UnityEngine.Debug.LogWarningFormat(System.String,System.Object[])). Addressables logs warnings and errors so by default this function will log.
///
/// The string with format tags.
/// The args used to fill in the format tags.
///
///
///
public static void LogWarningFormat(string format, params object[] args)
{
m_Addressables.LogWarningFormat(format, args);
}
///
/// Write an error level log message.
///
///
/// LogError can be used to write an Error message. LogError works the same way as . Addressables logs warnings and errors so by default this function will log.
///
/// The msg to log
///
/// Enable all logging
public static void LogError(string msg)
{
m_Addressables.LogError(msg);
}
///
/// Write an exception as a log message.
///
///
/// LogException can be used to convert an exception to a log message. The exception is stringified. If the operation is in a failed state, the exception is logged at an Error logging level. If not the exception is logged at a Debug logging level.
/// Addressables logs warnings and errors so if the operation is not in a failed state by default this function will not log.
///
/// The operation handle.
/// The exception.
///
///
///
/// Enable all logging
public static void LogException(AsyncOperationHandle op, Exception ex)
{
m_Addressables.LogException(op, ex);
}
///
/// Write an exception as a debug log message.
///
///
/// LogException can be used to convert an exception to a log message. The exception is stringified and logged at a Debug logging level. Addressables logs warnings and errors so by default this function will not log.
///
/// The exception.
///
///
///
public static void LogException(Exception ex)
{
m_Addressables.LogException(ex);
}
///
/// Write an error level formatted log message.
///
///
/// LogErrorFormat can be used to write a formatted Error level log message. LogErrorFormat supports Composite Formatting and works the same way as . Addressables logs warnings and errors so by default this function will log.
///
/// The string with format tags.
/// The args used to fill in the format tags.
///
///
///
public static void LogErrorFormat(string format, params object[] args)
{
m_Addressables.LogErrorFormat(format, args);
}
///
/// Initialize Addressables system. Addressables will be initialized on the first API call if this is not called explicitly.
///
/// The operation handle for the request.
///
//[Obsolete("We have added Async to the name of all asynchronous methods (UnityUpgradable) -> InitializeAsync(*)", true)]
[Obsolete]
public static AsyncOperationHandle Initialize()
{
return InitializeAsync();
}
///
/// Initialize the Addressables system, if needed.
///
///
/// The Addressables system initializes itself at runtime the first time you call an Addressables API function.
/// You can call this function explicitly to initialize Addressables earlier. This function does nothing if
/// initialization has already occurred.
///
/// Other Addressables API functions such as LoadAssetAsync also automatically initializes the
/// system if not already initialized. However in some cases you may wish to explicitly initalize Addressables,
/// for example to check if the initialization process completed successfully before proceeding to load Addressables
/// assets. Initializing explicitly shortens the execution time of the subsequent Addressables API function call
/// because the initialization process is already completed.
///
/// The initialization process loads configuration data and the local content catalog. Custom initialization
/// tasks can also be included in this process, for example loading additional remote catalogs.
/// See [Customizing Addressables Initialization](xref:addressables-api-initialize-async) for more information.
///
/// The initialization process:
/// * Sets up the and
/// * Loads the object, which is created by the Addressables build
/// * Executes operations
/// * Optionally, checks for an updated content catalog (`true` by default)
/// * Loads the content catalog
///
/// The `Result` object contained in the returned by this function
/// contains a list of Addressable keys and a method that can be used to gather the
/// instances for a given key and asset type. You must access the `Result` object in a
/// event handler. To access the handle in a coroutine or Task-based function, pass `false` to the
/// overload of this function. Otherwise, the Addressables system
/// releases the object before control returns to your code.
///
/// AsyncOperationHandle that is used to check when the operation has completed. The result of the operation is an [IResourceLocator](xref:UnityEngine.AddressableAssets.ResourceLocators.IResourceLocator) object.
///
/// The following script loads all Addressable assets referenced in the catalog.
///
///
/// Managing catalogs at runtime
public static AsyncOperationHandle InitializeAsync()
{
return m_Addressables.InitializeAsync();
}
///
/// Initialize the Addressables system, if needed.
///
/// Determines if the handle should be released on completion, or manually released.
/// AsyncOperationHandle that is used to check when the operation has completed. The result of the operation is an [IResourceLocator](xref:UnityEngine.AddressableAssets.ResourceLocators.IResourceLocator) object.
public static AsyncOperationHandle InitializeAsync(bool autoReleaseHandle)
{
return m_Addressables.InitializeAsync(autoReleaseHandle);
}
///
/// Additively load catalogs from runtime data. The settings are not used.
///
/// The path to the runtime data.
/// This value, if not null or empty, will be appended to all provider ids loaded from this data.
/// The operation handle for the request.
//[Obsolete("We have added Async to the name of all asynchronous methods (UnityUpgradable) -> LoadContentCatalogAsync(*)", true)]
[Obsolete]
public static AsyncOperationHandle LoadContentCatalog(string catalogPath, string providerSuffix = null)
{
return LoadContentCatalogAsync(catalogPath, providerSuffix);
}
///
/// Additively load catalogs from runtime data.
///
///
/// You can cache content catalog by providing the hash file created for the catalog by the Addressables content build
/// at the same URL as the catalog JSON file. The Addressables system uses this hash file to determine if the cached catalog
/// needs to be updated. If the value in the hash file has not changed since the last time you loaded the same catalog,
/// this function loads the cached version instead of downloading the catalog. If the hash value has changed or if no
/// hash file is provided, Addressables downloads the catalog from the specified path before loading it into memory.
///
/// See also: [Managing catalogs at runtime](xref:addressables-api-load-content-catalog-async)
///
/// The path to the runtime data.
/// This value, if not null or empty, will be appended to all provider ids loaded from this data.
/// The operation handle for the request.
public static AsyncOperationHandle LoadContentCatalogAsync(string catalogPath, string providerSuffix = null)
{
return m_Addressables.LoadContentCatalogAsync(catalogPath, false, providerSuffix);
}
///
/// Additively load catalogs from runtime data.
///
///
/// You can cache content catalog by providing the hash file created for the catalog by the Addressables content build
/// at the same URL as the catalog JSON file. The Addressables system uses this hash file to determine if the cached catalog
/// needs to be updated. If the value in the hash file has not changed since the last time you loaded the same catalog,
/// this function loads the cached version instead of downloading the catalog. If the hash value has changed or if no
/// hash file is provided, Addressables downloads the catalog from the specified path before loading it into memory.
///
/// See also: [Managing catalogs at runtime](xref:addressables-api-load-content-catalog-async)
///
/// The path to the runtime data.
/// If true, the async operation handle will be automatically released on completion. Typically,
/// there is no reason to hold on to the handle for this operation.
/// This value, if not null or empty, will be appended to all provider ids loaded from this data.
/// The operation handle for the request.
public static AsyncOperationHandle LoadContentCatalogAsync(string catalogPath, bool autoReleaseHandle, string providerSuffix = null)
{
return m_Addressables.LoadContentCatalogAsync(catalogPath, autoReleaseHandle, providerSuffix);
}
///
/// Initialization operation. You can register a callback with this if you need to run code after Addressables is ready. Any requests made before this operaton completes will automatically cahin to its result.
///
///
[Obsolete]
public static AsyncOperationHandle InitializationOperation => default;
///
/// Load a single asset
///
/// The type of the asset.
/// The location of the asset.
/// Returns the load operation.
///
//[Obsolete("We have added Async to the name of all asynchronous methods (UnityUpgradable) -> LoadAssetAsync(*)", true)]
[Obsolete]
public static AsyncOperationHandle LoadAsset(IResourceLocation location)
{
return LoadAssetAsync(location);
}
///
/// Load a single asset
///
/// The type of the asset.
/// The key of the location of the asset.
/// Returns the load operation.
///
//[Obsolete("We have added Async to the name of all asynchronous methods (UnityUpgradable) -> LoadAssetAsync(*)", true)]
[Obsolete]
public static AsyncOperationHandle LoadAsset(object key)
{
return LoadAssetAsync(key);
}
///
/// Loads a single Addressable asset identified by an .
///
///
/// Loads an Addressable asset. If a `key` references multiple assets (i.e. a label that is assigned to multiple assets), only the first asset found will be loaded.
///
/// When you load an Addressable asset, the system:
/// * Gathers the asset's dependencies
/// * Downloads any remote AssetBundles needed to load the asset or its dependencies
/// * Loads the AssetBundles into memory
/// * Populates the `Result` object of the instance returned by this function.
///
/// The type of the asset.
/// The location of the asset.
/// AsyncOperationHandle that is used to check when the operation has completed. The result of the operation is the loaded asset of the type `TObject`.
/// Loading Addressable Assets
/// Operations
///
/// The example below loads a material using an . The loaded material is assigned to a GameObject.
/// A reference to the operation handle is stored and can be released via .
///
///
///
/// The example below loads a material using a `key`, specifically an . The loaded material is assigned to a GameObject. A reference to the
/// operation handle is stored and can be released via .
///
///
public static AsyncOperationHandle LoadAssetAsync(IResourceLocation location)
{
return m_Addressables.LoadAssetAsync(location);
}
///
/// Loads a single Addressable asset identified by an .
///
/// The type of the asset.
/// The key of the location of the asset.
/// AsyncOperationHandle that is used to check when the operation has completed. The result of the operation is the loaded asset of the type `TObject`.
public static AsyncOperationHandle LoadAssetAsync(object key)
{
return m_Addressables.LoadAssetAsync(key);
}
///
/// Loads the resource locations specified by the keys.
/// The method will always return success, with a valid IList of results. If nothing matches keys, IList will be empty
///
/// The set of keys to use.
/// The mode for merging the results of the found locations.
/// A type restriction for the lookup. Only locations of the provided type (or derived type) will be returned.
/// The operation handle for the request.
//[Obsolete("We have added Async to the name of all asynchronous methods (UnityUpgradable) -> LoadResourceLocationsAsync(*)", true)]
[Obsolete]
public static AsyncOperationHandle> LoadResourceLocations(IList