No MergeMode is set to merge the multiple keys requested.

Hi,

Ive been having a weird issues using addressables, which is probably down to my lack of understanding of how it works. I have a simple mono class which takes an AssetReference and loads it on start. It has been fine in Editor (well it was for a while) but on final build the first item on the list failed to load. I couldnt reproduce the issue in Editor until now.

UnityEngine.AddressableAssets.InvalidKeyException: Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. No MergeMode is set to merge the multiple keys requested. Keys=, Type=UnityEngine.Sprite
UnityEngine.AddressableAssets.Addressables:LoadAssetAsync<UnityEngine.Sprite> (object)
Managers.AddressablesManager/<AddressAsset>d__6`1<UnityEngine.Sprite>:MoveNext () (at Assets/Scripts/Managers/AddressablesManager.cs:42)
UnityEngine.MonoBehaviour:StartCoroutine (System.Collections.IEnumerator)
Managers.AddressablesManager:GetAssetReference<UnityEngine.Sprite> (UnityEngine.AddressableAssets.AssetReference,ZForward.AddressableManager.AssetManagement.ScriptableObjects.AssetSo/AssetInstantiateType,UnityEngine.Transform,UnityEngine.Events.UnityAction`1<UnityEngine.Sprite>) (at Assets/Scripts/Managers/AddressablesManager.cs:34)
UI.AddressableImageLoader:Start () (at Assets/Scripts/UI/AddressableImageLoader.cs:20)

But heres the weird thing, i use LoadAssetAsync OR InstantiateAsync which does not take MergeMode. Here is my code.

    public class AddressableImageLoader : MonoBehaviour
    {
        public AssetReference image;
        public Image destination;
        public GameObject loading;
        private bool _isLoadingNotNull;

        // Start is called before the first frame update
        private void Start()
        {
            _isLoadingNotNull = loading != null;
            AddressablesManager.Instance.GetAssetReference<Sprite>(image, AssetSo.AssetInstantiateType.Load, null, OnImageLoad);
        }

        private void OnImageLoad(Sprite sprite)
        {
            destination.sprite = sprite;
            destination.color = Color.white;
        
            if (_isLoadingNotNull) loading.SetActive(false);
        }
    
    }
public class AddressablesManager : Singleton<AddressablesManager>
    {
        // How often in seconds to check for catalog update
        public bool checkForUpdates = true;
        public float updateCheckTime = 30f;
        private float _nextActionTime = 0.0f;
    
        private void Start()
        {
            CheckForUpdates();
        }
    
        private void Update()
        {
            if (!checkForUpdates) return;
            if (!(Time.time > _nextActionTime)) return;
            _nextActionTime += updateCheckTime;
            CheckForUpdates();
        }

        public void GetAssetReference<T>(AssetReference assetReference, AssetSo.AssetInstantiateType type = AssetSo.AssetInstantiateType.Instantiate, Transform parent = null, UnityAction<T> onSucceed = null)
        {
            StartCoroutine(AddressAsset<T>(assetReference, type, parent, onSucceed));
        }

        private static IEnumerator AddressAsset<T>(AssetReference assetReference, AssetSo.AssetInstantiateType type = AssetSo.AssetInstantiateType.Instantiate, Transform parent = null, UnityAction<T> onSucceed = null)
        {
            AsyncOperationHandle handle = type switch
            {
                AssetSo.AssetInstantiateType.Instantiate => Addressables.InstantiateAsync(assetReference),
                AssetSo.AssetInstantiateType.Load => Addressables.LoadAssetAsync<T>(assetReference),
                _ => throw new ArgumentOutOfRangeException()
            };

            yield return handle;
        
            if(handle.Status == AsyncOperationStatus.Succeeded)
            {
                onSucceed?.Invoke((T)handle.Result);
            }
        }
    
        private static void CheckForUpdates()
        {
            Addressables.CheckForCatalogUpdates();
        }
    
        public static void ForceUpdates()
        {
            // We had to update to 1.19.X to get this function
            Addressables.CleanBundleCache();
            CheckForUpdates();
        }
    
    }

Im really lost to what is causing this. Any help will be appreciated.

Below is an image of what its doing on Mobile. First run always works fine (All images load fine), as soon as we restartthe app, the top left image, which is first to load, doesnt actually load.

So there was multiple issues that i didnt reckonise at first. The errors i was getting above was due to a reference i left over in the scene so it was trying to load twice.

This however didnt fix the issue of the first image not loading. This issue was due to me trying to update addressable on app start.

Addressables.CheckForCatalogUpdates();

Hi @markmozza are AddressablesManager.Start() and AddressableImageLoader.Start() running at the same time when the first image is being loaded?

Addressables has an initialization process that occurs automatically when calling an Addressables API (i.e. LoadAssetAsync or CheckForCatalogUpdates) for the first time. I think what’s happening here is that the image is being loaded before initialization has completed.
https://docs.unity3d.com/Packages/com.unity.addressables@1.20/manual/InitializeAsync.html

So what you could do is manually call Addressables.InitializeAsync to trigger the initialization process. Once that operation has completed, then try to load the images.
https://docs.unity3d.com/Packages/com.unity.addressables@1.20/api/UnityEngine.AddressableAssets.Addressables.InitializeAsync.html#UnityEngine_AddressableAssets_Addressables_InitializeAsync

1 Like

Hi @pillakirsten , We resolved the issue now. It was my lack of understanding, it was exactly how you said. Thanks for the update.

1 Like