internal AsyncOperationHandle <TObject> GetAssetAsync <TObject>(AssetTableEntry entry) where TObject : Object { if (!entry.AsyncOperation.HasValue) { // Empty entries are treated as null. if (string.IsNullOrEmpty(entry.Guid)) { entry.AsyncOperation = ResourceManager.CreateCompletedOperation <TObject>(null, null); } else { entry.AsyncOperation = AddressablesInterface.LoadAssetFromGUID <TObject>(entry.Guid); } } var operation = entry.AsyncOperation.Value; try { return(operation.Convert <TObject>()); } catch (InvalidCastException) { // If we preloaded then the operation will be of type AsyncOperationHandle<Object[]> however we now // need to extract the asset and convert to AsyncOperationHandle<TObject>. if (operation.IsDone) { if (operation.Status != AsyncOperationStatus.Succeeded) { return(ResourceManager.CreateCompletedOperation <TObject>(null, operation.OperationException.Message)); } // Extract the asset from the array of preloaded sub objects. if (operation.Result is Object[] subObjects) { foreach (var obj in subObjects) { if (obj is TObject target) { var convertedCompletedOperation = ResourceManager.CreateCompletedOperation(target, null); entry.AsyncOperation = convertedCompletedOperation; AddressablesInterface.Release(operation); // Release the old operation return(convertedCompletedOperation); } } } throw new InvalidCastException($"Could not convert asset of type {operation.Result.GetType().Name} to {typeof(TObject).Name}."); } // Wait for the operation to complete before attempting again var convertedOperation = ResourceManager.CreateChainOperation(operation, (op) => GetAssetAsync <TObject>(entry)); entry.AsyncOperation = convertedOperation; AddressablesInterface.Release(operation); // Release the old operation return(convertedOperation); } }
AsyncOperationHandle PreloadAssets() { // Check the metadata to see if we should preload. First we check the table preload data, if one does not exist then check the key database(global). var preload = GetMetadata <PreloadAssetTableMetadata>() ?? SharedData.Metadata.GetMetadata <PreloadAssetTableMetadata>(); // If no preload metadata was found then we will preload all assets by default. if (preload?.Behaviour != PreloadAssetTableMetadata.PreloadBehaviour.NoPreload) { var handleList = ListPool <AsyncOperationHandle> .Get(); // Preload all foreach (var entry in Values) { if (!entry.IsEmpty && !entry.AsyncOperation.HasValue) { // We have to preload the asset as an array so that we get all sub objects. The reason for this is that some assets, // such as Sprite can contain multiple sub objects and if we load it as Object then we may get the wrong one. // For example, if we load a Sprite as an Object and it has the same name as its Texture asset then it will load as a Texture, // not Sprite. So if we load as an array we get both, we can then pick the one we need later based on the type passed into GetAssetAsync. (LOC-143) entry.AsyncOperation = AddressablesInterface.LoadAssetFromGUID <Object[]>(entry.Guid); ResourceManager.Acquire(entry.AsyncOperation.Value); handleList.Add(entry.AsyncOperation.Value); } } if (handleList.Count > 0) { return(ResourceManager.CreateGenericGroupOperation(handleList)); } else { ListPool <AsyncOperationHandle> .Release(handleList); } } // Nothing to preload, we are done return(ResourceManager.CreateCompletedOperation(this, null)); }