Addressables-Sample icon indicating copy to clipboard operation
Addressables-Sample copied to clipboard

Play Asset Delivery Integration Attempting to use an invalid operation handle error.

Open vahapcirag opened this issue 2 years ago • 6 comments

Hi!

I am using Addressables Package "1.19.17" to create asset bundles on "Unity 2020.3.27f1" and I am getting this error:

Exception: Attempting to use an invalid operation handle

Call Stack: UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1[TObject].get_InternalOp () (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1[TObject].get_Result () (at <00000000000000000000000000000000>:0) UnityEngine.AddressableAssets.Initialization.InitializationOperation.Execute () (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].InvokeExecute () (at <00000000000000000000000000000000>:0) System.Action1[T].Invoke (T obj) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1+<>c__DisplayClass58_0[TObject].<add_CompletedTypeless>b__0 (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1[TObject] s) (at <00000000000000000000000000000000>:0) System.Action1[T].Invoke (T obj) (at <00000000000000000000000000000000>:0) DelegateList1[T].Invoke (T res) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].InvokeCompletionEvent () (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].Complete (TObject result, System.Boolean success, System.Exception exception, System.Boolean releaseDependenciesOnFailure) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].Complete (TObject result, System.Boolean success, System.String errorMsg, System.Boolean releaseDependenciesOnFailure) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].Complete (TObject result, System.Boolean success, System.String errorMsg) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.InitalizationObjectsOperation.<Execute>b__8_0 (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1[TObject] obj) (at <00000000000000000000000000000000>:0) System.Action1[T].Invoke (T obj) (at <00000000000000000000000000000000>:0) DelegateList1[T].Invoke (T res) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].InvokeCompletionEvent () (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].Complete (TObject result, System.Boolean success, System.Exception exception, System.Boolean releaseDependenciesOnFailure) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.GroupOperation.CompleteIfDependenciesComplete () (at <00000000000000000000000000000000>:0) System.Action1[T].Invoke (T obj) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1+<>c__DisplayClass58_0[TObject].<add_CompletedTypeless>b__0 (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1[TObject] s) (at <00000000000000000000000000000000>:0) System.Action1[T].Invoke (T obj) (at <00000000000000000000000000000000>:0) DelegateList1[T].Invoke (T res) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].InvokeCompletionEvent () (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].Complete (TObject result, System.Boolean success, System.Exception exception, System.Boolean releaseDependenciesOnFailure) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].Complete (TObject result, System.Boolean success, System.String errorMsg, System.Boolean releaseDependenciesOnFailure) (at <00000000000000000000000000000000>:0) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase1[TObject].Complete (TObject result, System.Boolean success, System.String errorMsg) (at <00000000000000000000000000000000>:0) AddressablesPlayAssetDelivery.PlayAssetDeliveryInitializeOperation.CompleteOverride (System.String warningMsg) (at <00000000000000000000000000000000>:0) System.Action1[T].Invoke (T obj) (at <00000000000000000000000000000000>:0) System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <00000000000000000000000000000000>:0) System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <00000000000000000000000000000000>:0) UnityEngine.AndroidJavaProxy.Invoke (System.String methodName, System.Object[] args) (at <00000000000000000000000000000000>:0) UnityEngine._AndroidJNIHelper.InvokeJavaProxyMethod (UnityEngine.AndroidJavaProxy proxy, System.IntPtr jmethodName, System.IntPtr jargs) (at <00000000000000000000000000000000>:0) DelegateList1:Invoke(T) System.Action1:Invoke(T) DelegateList1:Invoke(T) System.Action1:Invoke(T) DelegateList1:Invoke(T) UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String) AddressablesPlayAssetDelivery.PlayAssetDeliveryInitializeOperation:CompleteOverride(String) UnityEngine._AndroidJNIHelper:InvokeJavaProxyMethod(AndroidJavaProxy, IntPtr, IntPtr)

vahapcirag avatar Mar 16 '22 08:03 vahapcirag

Having the same issue. Did you manage to fix it?

Dream-Engine-Games avatar Dec 28 '22 12:12 Dream-Engine-Games

We're also seeing this issue, using Addressables 1.20.5 Callstack is as follows System.Exception: Attempting to use an invalid operation handle File "AsyncOperationHandle.cs", line 213, in get_InternalOp File "AsyncOperationHandle.cs", line 278, in get_Result File "InitializationOperation.cs", line 95, in Execute File "AsyncOperationBase.cs", line 536, in InvokeExecute File "AsyncOperationBase.cs", line 148, in <.ctor>b__35_0 File "AsyncOperationBase.cs", line 330, in add_CompletedTypeless { <lambda> } File "Generics12.cpp", line 20941, in Invoke File "Generics47.cpp", in Invoke File "AsyncOperationBase.cs", line 395, in InvokeCompletionEvent File "AsyncOperationBase.cs", line 508, in Complete File "Generics23.cpp", line 25763, in Complete File "AsyncOperationBase.cs", line 435, in Complete File "Unity.Addressables.cpp", line 9095, in Execute { <lambda> } File "Generics12.cpp", line 21097, in Invoke File "Generics47.cpp", in Invoke File "AsyncOperationBase.cs", line 395, in InvokeCompletionEvent File "AsyncOperationBase.cs", line 508, in Complete File "Unity.ResourceManager.cpp", line 35049, in CompleteIfDependenciesComplete File "GroupOperation.cs", line 228, in OnOperationCompleted File "AsyncOperationBase.cs", line 330, in add_CompletedTypeless { <lambda> } File "Generics12.cpp", line 20941, in Invoke File "Generics47.cpp", in Invoke File "AsyncOperationBase.cs", line 395, in InvokeCompletionEvent File "AsyncOperationBase.cs", line 508, in Complete File "Generics23.cpp", line 25763, in Complete File "AsyncOperationBase.cs", line 435, in Complete File "PlayAssetDeliveryInitialization.cs", line 76, in CompleteOverride File "AddressablesPlayAssetDelivery.cpp", line 4686, in DownloadCustomAssetPacksData { <lambda> }

JPerryOddGames avatar Jan 11 '23 03:01 JPerryOddGames

@kirstenpilla hi, do you have any idea what might cause this issue? We're using the code from the Play Asset Delivery sample project you added, and using Unity 2020.3.13f1 with addressables 1.20.5. The error occurs at launch every session after the PlayAssetDeliveryInitializeOperation completes. Some callback assigned to the CompletedTypeless event throws an exception, but I've struggled to find out which class/method it is. Regardless I believe it's complaining that the PlayAssetDeliveryInitializeOperation itself is invalid. If you have any information or ideas to try, please advise, thank you!

JPerryOddGames avatar Jan 18 '23 23:01 JPerryOddGames

@JPerryOddGames Hello, have you solved the issue yet? I also have same problem but using Unity 2021.3.16 with latest addresssables. I believe the problem was ProvideHandle m_ProviderInterface in PlayAssetDeliveryAssetBundleProvider replaced by dependencies.

When Addressables.LoadAssetAsync<TResource>(resourceAddress), it will fetch the target resource and its all dependencies. Then the target resources is part of the asset pack and try to download it if not installed. Because the download method in PAD sample is void not async, it make execute the others dependencies where I believe generate new ProvideHandle then overwrite ProvideHandle m_ProviderInterface. So when the PAD download completed, the callback invoke other m_ProviderInterface.

image

restush avatar Jan 30 '23 05:01 restush

@JPerryOddGames After I make async, the dependencies will wait for download to be completed. So there is no invalid handle any more because overwritten the m_ProviderInterface. Here is my modified codes. Notice I move m_ProviderInterface = providerInterface; from Provide method to LoadFromAssetPack method and add while loop before it.

image

restush avatar Jan 30 '23 07:01 restush

Apologies @restush , I never received a notification from your replies in this thread. We did manage to solve the issue on the 1st of Feb and have not seen it since (in 10 weeks) so I assume it's entirely fixed.

I'll include my fix below. Note that m_ProviderInterface no longer exists in class-scope at all; Instead, the object is passed directly to the methods that require it.

Code
using System;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Android;
using UnityEngine.ResourceManagement.ResourceProviders;

namespace AddressablesPlayAssetDelivery
{
    /// <summary>
    /// Ensures that the asset pack containing the AssetBundle is installed/downloaded before attemping to load the bundle.
    /// </summary>
    [DisplayName("Play Asset Delivery Provider")]
    public class PlayAssetDeliveryAssetBundleProvider : AssetBundleProvider
    {
        public override void Provide(ProvideHandle providerInterface)
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            LoadFromAssetPack(providerInterface);
#else
            base.Provide(providerInterface);
#endif
        }

#if UNITY_ANDROID
        private void LoadFromAssetPack(ProvideHandle providerInterface)
        {
            string bundleName = Path.GetFileNameWithoutExtension(providerInterface.Location.InternalId);
            if (!PlayAssetDeliveryRuntimeData.Instance.BundleNameToAssetPack.ContainsKey(bundleName))
            {
                // Bundle is either assigned to the generated asset packs, or not assigned to any asset pack
                base.Provide(providerInterface);
            }
            else
            {
                // Bundle is assigned to a custom fast-follow or on-demand asset pack
                string assetPackName = PlayAssetDeliveryRuntimeData.Instance.BundleNameToAssetPack[bundleName].AssetPackName;
                if (PlayAssetDeliveryRuntimeData.Instance.AssetPackNameToDownloadPath.ContainsKey(assetPackName))
                {
                    // Asset pack is already downloaded
                    base.Provide(providerInterface);
                }
                else
                {
                    // Download the asset pack
                    DownloadRemoteAssetPack(assetPackName, providerInterface);
                }
            }
        }

        private async void DownloadRemoteAssetPack(string assetPackName, ProvideHandle providerInterface)
        {
            // Note that most methods in the AndroidAssetPacks class are either direct wrappers of java APIs in Google's PlayCore plugin,
            // or depend on values that the PlayCore API returns. If the PlayCore plugin is missing, calling these methods will throw an InvalidOperationException exception.
            try
            {
                await ProcessRequest(Google.Play.AssetDelivery.PlayAssetDelivery.RetrieveAssetPackAsync(assetPackName), assetPackName, providerInterface);
            }
            catch (InvalidOperationException ioe)
            {
                Debug.LogError($"Cannot retrieve state for asset pack '{assetPackName}'. PlayCore Plugin is not installed: {ioe.Message}");
                providerInterface.Complete(this, false, new Exception("exception"));
            }
        }

        private async Task ProcessRequest(Google.Play.AssetDelivery.PlayAssetPackRequest request, string assetPackName, ProvideHandle providerInterface)
        {
            while (!request.IsDone)
                await System.Threading.Tasks.Task.Yield();

            Debug.Log($"[PlatAssetDeliveryBundleProvider] {assetPackName} finished downloading, now waiting for installation");

            while (request.Error != Google.Play.AssetDelivery.AssetDeliveryErrorCode.NoError && (request.Status != Google.Play.AssetDelivery.AssetDeliveryStatus.Available || request.Status != Google.Play.AssetDelivery.AssetDeliveryStatus.Loaded))
                await System.Threading.Tasks.Task.Yield();

            Debug.Log($"[PlatAssetDeliveryBundleProvider] {assetPackName} finished waiting status: {request.Status}, error: {request.Error}");

            string message = string.Empty;
            if (request.Error != Google.Play.AssetDelivery.AssetDeliveryErrorCode.NoError)
                message = $"Failed to retrieve the state of asset pack '{assetPackName}'.";
            else
            {
                string assetPackPath = AndroidAssetPacks.GetAssetPackPath(assetPackName);

                if (!string.IsNullOrEmpty(assetPackPath))
                {
                    // Asset pack was located on device. Proceed with loading the bundle.
                    PlayAssetDeliveryRuntimeData.Instance.AssetPackNameToDownloadPath[assetPackName] = assetPackPath;
                    base.Provide(providerInterface);
                }
                else
                    message = $"Downloaded asset pack '{assetPackName}' but cannot locate it on device.";
            }

            if (!string.IsNullOrEmpty(message))
            {
                Debug.LogError(message);
                providerInterface.Complete(this, false, new Exception("exception"));
            }
        }
#endif
    }
}

JPerryOddGames avatar Apr 12 '23 03:04 JPerryOddGames