Exception: Attempting to use an invalid operation handle

Hi,

I have an error coming from the Addressables system when switching scenes.

I’ve narrowed it down that it only happens when switching a scene after I’ve used a script that uses the addressables system.

I’m weeks away from releasing my game on steam so updating Unity or the Addressables system is not really something I’m considering. Unless absolutely necessary.

I’m using
Unity 2020.3
Addressables 1.19.4

The use case for using the addressables system here is to show short videos tutorials as tips. I’m going to have a lot of those, and loading all of them in memory does not make much sense. So instead I load/show one at a time. And I have button to show next/previous so that you can quickly go through the tips.

My script does a lot of stuff but the main part that loads/unloads is this:

private void LoadContent(int index)
    {
        //if(m_References[index].IsValid() && m_References[index].IsDone)
        m_AsyncOperationHandles[index] = m_References[index].LoadAssetAsync<GameObject>();
       
        /*m_AsyncOperationHandles[index].Completed += (handle) =>
        {
            if(handle.Result == null){ return;}
            handle.Result.transform.SetSiblingIndex(0);
        };*/
        m_Loaded[index] = true;

        for (int i = 0; i < m_Loaded.Length; i++) {
            if (i != index && m_Loaded[i] && m_AsyncOperationHandles[i].IsValid() && m_AsyncOperationHandles[i].Status == AsyncOperationStatus.Succeeded) {
                m_Loaded[i] = false;
                m_References[i].ReleaseAsset();
                m_AsyncOperationHandles[i] = new AsyncOperationHandle<GameObject>();
            }
        }
    }

Then I wait until it is done:

if (m_AsyncOperationHandles[m_Index].IsDone) {
    m_State = TipsPanelState.DisolveIn;

    if (m_CurrentPage != null) {
        m_References[m_PreviousShownIndex].ReleaseInstance(m_CurrentPage);
        if (m_References[m_PreviousShownIndex].OperationHandle.IsValid()) {
            m_References[m_PreviousShownIndex].ReleaseAsset();
        }
    }

    var asyncOperation = m_References[m_Index].InstantiateAsync(m_ContentParent, false);
    asyncOperation.Completed += (handle) =>
    {
        if (handle.Result != null) {
            m_CurrentPage = handle.Result;
            m_CurrentPage.GetComponent<TipsContent>()?.OpenInPanel(this);
        }
    };
    m_PreviousShownIndex = m_Index;
}

I also unload on disable:

    private void OnDisable()
    {
        ListenToInput(false);
       
        //Release all the assets.
        for (int i = 0; i < m_Loaded.Length; i++) {
            //if (!m_Loaded[i]) { continue; }
            m_Loaded[i] = false;
           
            if (m_References[i].IsValid() == false) { continue; }

            m_References[i].ReleaseInstance(m_AsyncOperationHandles[i].Result);
            m_References[i].ReleaseAsset();
            m_AsyncOperationHandles[i] = new AsyncOperationHandle<GameObject>();
        }

        m_CurrentPage = null;
    }

Here is the error when I switch scenes

Exception: Attempting to use an invalid operation handle
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.get_InternalOp () (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:453)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDependencies (System.Collections.Generic.List`1[T] deps) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs:436)
UnityEngine.AddressableAssets.Utility.ResourceManagerDiagnostics.SumDependencyNameHashCodes (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle handle) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/Utility/ResourceManagerEventCollector.cs:43)
UnityEngine.AddressableAssets.Utility.ResourceManagerDiagnostics.SumDependencyNameHashCodes (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle handle) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/Utility/ResourceManagerEventCollector.cs:49)
UnityEngine.AddressableAssets.Utility.ResourceManagerDiagnostics.CalculateHashCode (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle handle) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/Utility/ResourceManagerEventCollector.cs:59)
UnityEngine.AddressableAssets.Utility.ResourceManagerDiagnostics.OnResourceManagerDiagnosticEvent (UnityEngine.ResourceManagement.ResourceManager+DiagnosticEventContext eventContext) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/Utility/ResourceManagerEventCollector.cs:120)
UnityEngine.ResourceManagement.ResourceManager.PostDiagnosticEvent (UnityEngine.ResourceManagement.ResourceManager+DiagnosticEventContext context) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/ResourceManager/ResourceManager.cs:321)
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1[TObject].DecrementReferenceCount () (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs:174)
UnityEngine.ResourceManagement.ResourceManager.CleanupSceneInstances (UnityEngine.SceneManagement.Scene scene) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/ResourceManager/ResourceManager.cs:1021)
UnityEngine.AddressableAssets.AddressablesImpl.OnSceneUnloaded (UnityEngine.SceneManagement.Scene scene) (at Library/PackageCache/com.unity.addressables@1.19.4/Runtime/AddressablesImpl.cs:197)
UnityEngine.SceneManagement.SceneManager.Internal_SceneUnloaded (UnityEngine.SceneManagement.Scene scene) (at <3be1a7ff939c43f181c0a10b5a0189ac>:0)

My guess is that I’m not properly loading/releasing the object. But I don’t really understand why.

Any advice would be highly approciated

After some trial and error I think I was able to fix it.
Turns out I wasn’t cleaning up properly the currently loaded page on disable.

So after releasing the instance of the current page on disable it seems that it fixed the issue when switching scenes.

private void Cleanup()
    {
        if (m_CurrentPage != null) {
            m_References[m_Index].ReleaseInstance(m_CurrentPage);
            if (m_References[m_Index].OperationHandle.IsValid()) { m_References[m_Index].ReleaseAsset(); }
        }

        //Release all the assets.
        for (int i = 0; i < m_Loaded.Length; i++) {
            //if (!m_Loaded[i]) { continue; }
            m_Loaded[i] = false;

            if (m_References[i].IsValid() == false) { continue; }

            if (m_AsyncOperationHandles[i].IsValid() == false) { continue; }

            m_References[i].ReleaseInstance(m_AsyncOperationHandles[i].Result);
            m_References[i].ReleaseAsset();
            m_AsyncOperationHandles[i] = new AsyncOperationHandle<GameObject>();
        }

        m_CurrentPage = null;
    }
1 Like