Search Unity

Question I think i don't understand how CheckForCatalogUpdates work

Discussion in 'Addressables' started by Deathtreak, Jun 3, 2020.

  1. Deathtreak

    Deathtreak

    Joined:
    Nov 19, 2017
    Posts:
    17
    Hi,

    I need some help with Addressables...
    I'm trying to make a small Update System for future project, and i'm stuck with CheckForCatalogUpdates...
    Disable Catalog Update is checked in Addressable Asset Settings
    But CheckForCatalogUpdates continue to return a list with a length of 0 even if there is changes

    With some testing, it appears that, if i upload an update on my CDN, Unity is able to instantiate the news Assets from the remote, but CheckForCatalogUpdates continue to return a length of 0

    Here is my testing code :

    Code (CSharp):
    1. public class Spawner : MonoBehaviour
    2. {
    3.     public AssetReference localGeometry;
    4.     private List<IResourceLocation> remoteGeometry;
    5.     public AssetLabelReference geometry;
    6.  
    7.     private void Start()
    8.     {
    9.         DisplayGeometry();
    10.  
    11.         Addressables.InitializeAsync().Completed += objects =>
    12.         {
    13.             Addressables.CheckForCatalogUpdates().Completed += checkforupdates =>
    14.             {
    15.                 if (checkforupdates.Result.Count > 0)
    16.                 {
    17.                     Debug.LogError("Available Update");      
    18.                     LocationLoaded(Addressables.LoadResourceLocationsAsync(geometry));
    19.                 }
    20.                 else
    21.                 {
    22.                     Debug.LogError("No Available Update");
    23.                     LocationLoaded(Addressables.LoadResourceLocationsAsync(geometry));
    24.                 }
    25.  
    26.             };
    27.         };
    28.  
    29.     }
    30.  
    31.     private void DisplayGeometry()
    32.     {
    33.         localGeometry.InstantiateAsync(Vector3.zero, Quaternion.identity);
    34.         Debug.Log(geometry.labelString);
    35.     }
    36.  
    37.     private void LocationLoaded(AsyncOperationHandle<IList<IResourceLocation>> obj)
    38.     {
    39.         remoteGeometry = new List<IResourceLocation>(obj.Result);
    40.  
    41.         StartCoroutine(SpawnRemoteGeometry());
    42.     }
    43.  
    44.     private IEnumerator SpawnRemoteGeometry()
    45.     {
    46.         yield return new WaitForSeconds(1f);
    47.         float xOff = -4.0f;
    48.  
    49.         for (int i = 0; i < remoteGeometry.Count; i++)
    50.         {
    51.             Vector3 spawnPosition = new Vector3(xOff, 3, 0);
    52.  
    53.             Addressables.InstantiateAsync(remoteGeometry[i], spawnPosition, Quaternion.identity);
    54.  
    55.             xOff = xOff + 10;
    56.             yield return new WaitForSeconds(1f);
    57.         }
    58.     }
    59. }
    When i do change on my remote assets, i can see the change in the scene (more or less object spawned in the scene according to the catalog on the CDN)

    So my question is: why CheckForCatalogUpdates awlays return me nothing ? Did i miss a step ?
    I'm stuck since 3days and it drives me crazy, any help would be appreciated

    PS: Debug.LogError is used to see messages in console on my Developement Build.

    Thanks.
     
  2. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    You probably have check for catalog updates on startup checked in your addressable settings, so your extra check in code right after initialization is redundant and does nothing. The CheckForCatalogUpdates API is meant to be used during normal runtime to periodically check for updates so that the player doesn't need to restart the app.
     
  3. Deathtreak

    Deathtreak

    Joined:
    Nov 19, 2017
    Posts:
    17
    I said "Disable Catalog Update is checked in Addressable Asset Settings", so i think this is not the issue i'm facing
     
    Last edited: Jun 3, 2020
  4. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    Oh sorry, I missed that part.
     
  5. Deathtreak

    Deathtreak

    Joined:
    Nov 19, 2017
    Posts:
    17
    Np ^^
     
  6. Deathtreak

    Deathtreak

    Joined:
    Nov 19, 2017
    Posts:
    17
  7. Deathtreak

    Deathtreak

    Joined:
    Nov 19, 2017
    Posts:
    17
    Anyone ? I'm still stuck :/

    Edit : Status = Completed, IsDone = true while checking with breakpoint on the if/else statement, but Result.Count is still 0
     
  8. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,822
    I'll flag this with the team, and pass along any guidance they have! Could you tell me which version of Addressables you're using?
     
  9. Deathtreak

    Deathtreak

    Joined:
    Nov 19, 2017
    Posts:
    17
    Thanks for your reply, i'm using the version 1.8.4 of Addressables since the beginning of this project and Unity 2019.3.14f1 Personnal.
     
  10. mateuszjaworski

    mateuszjaworski

    Joined:
    Aug 8, 2019
    Posts:
    12
    For me it returns 1 entry which is MainCatalog. It doesn't matter whether there is an update or not. Also when I use external server to download content update manually, it does not update content on the device, but it does in the editor. It would be great if you could share and example how to use it properly to make it work.
     
    J1wan likes this.
  11. Tayfe

    Tayfe

    Joined:
    Nov 21, 2011
    Posts:
    103
    I'm facing a smiliar problem: I get an update when I upload a new version to my server. The problem is that this update is done automatically but I want to do it manually! I have also checked "Disable Update on Startup" but it isn't changing anything. Updates are still done automatically. I am using Unity 2019.3.13f1 and addressables 1.10.0
     
  12. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,822
    Have an update from the team, it's possible this is a bug. Would you mind filing a bug report for us?

    Additionally, they are looking into creating a sample that shows how this works. It won't be any time soon, but they can make something like that and throw it into the Addressables Samples repository.
     
    batonPiotr and mateuszjaworski like this.
  13. mateuszjaworski

    mateuszjaworski

    Joined:
    Aug 8, 2019
    Posts:
    12
    Yes, please do it! :D
     
  14. Deathtreak

    Deathtreak

    Joined:
    Nov 19, 2017
    Posts:
    17
    The bug report is created :D
    But I don't know how to check for content update while waiting for the bug to be fixed :/
     
  15. Redtail87

    Redtail87

    Joined:
    Jul 17, 2013
    Posts:
    125
  16. Tayfe

    Tayfe

    Joined:
    Nov 21, 2011
    Posts:
    103
    Thanks for doing it! I was hoping for someone else creating one :D I think we will wait with this feature until it has been fixed. I don't want to spend time on a workaround when they will do it as well. I did this once before and 2 weeks later there was an update where they fixed it and all my work was overdue. So we will just hope they might fix it soon.
     
  17. batonPiotr

    batonPiotr

    Joined:
    Apr 8, 2016
    Posts:
    10
    Some updates on this one? I try to check if there are some updates on the catalog but there are always 0 elements in the list. Version I am using: 1.16.13 and Unity 2019.4.11f1
     
  18. batonPiotr

    batonPiotr

    Joined:
    Apr 8, 2016
    Posts:
    10
    I have found the reason why I didn't get the updates: you have to initialize the addressables system first with
    Code (CSharp):
    1. Addressables.InitializeAsync();
    and then you can use the other methods. I didn't initialize it manually because the documentation stated it would initialize automatically with first API call so I didn't bother.
     
    Trisibo likes this.
  19. Trisibo

    Trisibo

    Joined:
    Nov 1, 2010
    Posts:
    245
    Thanks a lot, consider yourself kissed, COVID or not.

    @TreyK-47 @davidla_unity Is this a bug, and if so it is known? If it isn't, please, you should update the documentation, because it says that Addressables.InitializeAsync is not needed to be called manually, and I can't find anything saying that it must be called before calling CheckForCatalogUpdates, I've been going completely crazy trying to make it work.
     
  20. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,822
    I'll kick this over for the team to have a look! Thanks for flagging!
     
  21. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    The problem here is how the internal caching is done with operations being performed. This works for all files being loaded.

    Firstly, when loading the catalog, (in your case from the cache, if you have "check on start" disabled). The operation to load the .hash and .json files are cached.
    The CheckForCatalogUpdates relies on the catalog operations not being cached in memory. In order to load the hash file and compare the values, comparing it to what is loaded in the system. When using LoadContentCatalogAsync this is done by passing "autoReleaseHandle = true", or releasing the operation handle after loading the catalog, to remove it from the cache.
    With Addressables.InitializeAsync, it will auto release after it is done.

    The issue here comes when registering to Addressables.InitializeAsync().Completed, when the method is invoked from this operation, so it currently cached, CheckForCatalogUpdates is then getting the cached hash value, instead of downloading the remote file and comparing values. Resulting it is always being "up to date".

    I will create a case internally to look into if there is anyway that we can support this. But for now I would recommend waiting until after .Completed:

    Code (CSharp):
    1. private IEnumerator Start()
    2. {
    3.     DisplayGeometry();
    4.     yield return Addressables.InitializeAsync();
    5.  
    6.     Addressables.CheckForCatalogUpdates().Completed += checkforupdates =>
    7.     {
    8.         if (checkforupdates.Result.Count > 0)
    9.         {
    10.             Debug.LogError("Available Update");    
    11.             LocationLoaded(Addressables.LoadResourceLocationsAsync(geometry));
    12.         }
    13.         else
    14.         {
    15.             Debug.LogError("No Available Update");
    16.             LocationLoaded(Addressables.LoadResourceLocationsAsync(geometry));
    17.         }
    18.     };
    19. }
     
  22. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
    I don't think I quite follow, I feel like you are discussing multiple cases of whether the Disable Catalog Update on Startup are checked or not, and your code only works for one of those assumptions.

    What I am seeing is, when I use that code, with the Disable Catalog Update on Startup checked in the editor, CheckForCatalogUpdates does nothing because AddressablesImpl.ResourceLocatorInfo.LocalHash is null, so CanUpdateContent is false
     
  23. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    Hi Chris,
    That sounds like a different issue. Local hash should not be null for remote catalogs.
    It could be that you do not have remote catalog enabled.
    You are not connected to the internet and there isn't yet a cached version of the remote catalog to get the local hash with. (This will fallback to the built-in catalog, which cannot update)
    Or you are not adding the .hash file to the same location as the .json file. So it will never be cached.
     
  24. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
    OK, yes if the client isn't connected to the Internet, or in my case, if you don't have the URL for the CDN for
    InternalIdTransformFunc until after Addressables initializes (due to usage of local bundles in the application), I don't see how to reinitialize Addressables properly once the client can connect to the catalog URL. It seems that once you initialize in these cases where local hash will be null, then CheckForClientUpdates always fails/skips the catalogs due to the localHash always being null. How do we reinitialize things properly so that localHash is not null?
     
  25. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
    I don't see an option to not use auto release handle with InitializeAsync, so don't you have to use Completed in the case of async/await with InitializeAsync? Then we can't use your workaround of using a coroutine yield, and we can't await the task returned because it is released?
     
    Last edited: Mar 30, 2021
  26. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    Check out this post I made a while ago that will allow you to await and still access the value before it's released (it's an extension that wraps Completed for the await keyword).

    https://forum.unity.com/threads/await-without-task.951329/
     
  27. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    If I am correct, this will never result in the catalog being able to update. Your issue does not appear to be when you call CheckForCatalogUpdates but that you are loading the local catalog, then attempting to update the local catalog. Expecting this to be the remote catalog.
    We will need to look into it further, and I have made a case internally to look into it.

    I would recommend looking to see if you can put your information about InternalIdTransformFunc usage to get your correct url outside of Addressables local build content. e.g. referencing it directly in the Player. And then use it when Initialising to get the catalog from the expected url.
     
    chrismarch likes this.
  28. HEROTECH70

    HEROTECH70

    Joined:
    May 24, 2017
    Posts:
    74
    I am sorry but this system is unnecessarily complicated,
    Nothing works not even the code posted above, trying to yield return the Addressables.InitializeAsync(); throws an exception because the operation is invalid.

    so I changed everything to use the onComplete events, now it works but no changes are being detected still

    What am I missing, I have been at this for a week now and this is getting ridiculous.
     
    JGameMaker92 likes this.
  29. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    That will not work, for the reason I mentioned. In the completed callback the catalog is cached, and will not be redownloaded to check for update.

    I do not know what could cause this, possibly a bug, If you can a bug report would be great so we can look at this locally.
     
  30. HEROTECH70

    HEROTECH70

    Joined:
    May 24, 2017
    Posts:
    74
  31. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    That is referring to the automatic catalog check and update.

    When you have both `remote catalog` enabled, and `Disable catalog update on startup` not set. Then the following happens before loading the catalog (This is not the same as CheckForContentUpdate and UpdateCatalog method calls, which update already loaded catalogs).

    Before loading the remote catalog, it will first check if it is in the cache. If not it will download
    If so, it will download the hash on the server.
    Then compare the server hash to the local cached hash
    If they are the same then it will load the local cached catalog
    If different they will download, cache and load the server version.
     
  32. HEROTECH70

    HEROTECH70

    Joined:
    May 24, 2017
    Posts:
    74
    What could be the cause of both updates failing?
    The automatic update on init doesn't work, and UpdateCatalog fails with a no update required exception
    Reinstalling the app updates the catalog.

    How do I even begin troubleshooting this?
     
  33. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    I would step through with an IDE and find where it fails.

    If you are doing everything as suggested it could be a bug, it may be good to create a bug report
     
  34. aromana

    aromana

    Joined:
    Nov 11, 2018
    Posts:
    137
    cc @davidla_unity

    I can confirm that
    CheckForCatalogUpdates()
    returns an empty list 100% of the time (whether there really is an update or not) UNLESS I await
    Addressables.InitializeAsync()
    before calling
    CheckForCatalogUpdates()
    . If I do call
    InitializeAsync()
    prior to
    CheckForCatalogUpdates()
    , the latter function works exactly as I expect.


    Just to be extremely clear (note I'm using UniTask async extensions for readability, but that shouldn't matter):

    This does work:
    Code (CSharp):
    1. await Addressables.InitializeAsync();
    2. // next line returns a non-empty list if updates are available, otherwise an empty list
    3. await Addressables.CheckForCatalogUpdates();
    This case doesn't work:
    Code (CSharp):
    1.  
    2. // note: InitializeAsync is NOT explicitly called
    3. // next line ALWAYS returns an empty list, regardless of remote content being updated or not
    4. await Addressables.CheckForCatalogUpdates();
    This behavior is unexpected and confusing, because the docs indicate clearly that Addressables will lazily initialize itself if not explicitly initialized. Per the docs:

    You can manually initialize Addressables, though it is not required, by calling Addressables.InitializeAsync(). This returns an AsyncOperationHandle. Do not release this handle while using Addressables.
    If Addressables is not manually initialized, by default Addressables checks that initialization has occurred. If the initial call, such as a LoadAsset request, detects that initialization has not occured then an InitilizationOperation is kicked off automatically. The LoadAsset operation is chained behind the initialization operation and executes automatically afterwards.

    Can you please confirm if this is indeed intended behavior (in which I would suggest the documentation be updated to clarify this) or if this is a bug?

    Other details about my setup if it's useful:

    Unity 2020.3.13f1 LTS
    Addressables 1.16.19 ("Verified")
    Addressables top level settings:
    • Disable Catalog Update on Startup: TRUE
    • Build Remote Catalog: TRUE
     
    JGameMaker92 likes this.
  35. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Hi @aromana based on the code that does appear to be the expected behavior. CheckForCatalogUpdates expects the Addressables.ResourceLocators list to be populated beforehand. I'll create a ticket to change the "lazy initialization" blanket statement in the docs.

    Also as a heads up there is a major rewrite of the Addressables documentation coming soon. The docs in general should be less confusing :)
     
    sniffle63, Redtail87 and aromana like this.
  36. aromana

    aromana

    Joined:
    Nov 11, 2018
    Posts:
    137
    Thanks very much! That's wonderful news. I will say the experience of learning addressables has been quite rough, but now that I understand it (at least well enough to implement it in my project), I'm generally quite happy with it. I think improving the documentation (and giving some updated talks!) will go a long way.
     
  37. TheNullReference

    TheNullReference

    Joined:
    Nov 30, 2018
    Posts:
    268
    Hey guys, I've been trying to follow along but unable to so far, I feel like what I'm trying to do is REALLY simple.

    If I've never used the app before (cache is empty). Addressables works like a charm, everything loads as is. After that point, it NEVER updates addressable content as long as the cache isn't empty. I'm using google cloud services as my remote, but that shouldn't matter.

    I just simply want to; Check if the content on the remote is different to the content in then cache. If it is, download the content on the remote.

    It's kind of annoying that "DownloadDependenciesAsync" Doesn't actually download anything if it detects something in the cache, even if it's out of the date. The developer provided some code specific to the original question, but yea, how would someone simply just, download updated content. Isn't this kind of a core part of this system? why does it seems so difficult.
     
    YifanYaoHabby likes this.
  38. HEROTECH70

    HEROTECH70

    Joined:
    May 24, 2017
    Posts:
    74
    It just doesn't work and trying to get an answer here has been really difficult
     
  39. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365

    Well that's a shame. Literally just spent the last 2 weeks converting asset bundles to addressables for my company and this is a main feature of what we have to do. and the docs make it seem simple.
    Going to do test myself because it seems impossible for this to not work. But still, a shame if so.
     
  40. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Hi @andymilsom What's the progress now?
     
  41. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    It may be fixed in 1.18.4 and above. But I haven't confirmed.
    Due to change in changelog: Fixed issue where remote .hash file was still being requested when Disable Content Catalog Update on Startup was enabled.

    However I would still not rely on being able to update the catalogs in Initialise handle .completed. This callback cannot really expect the handle to be released of the Initialise operation. Causing the updates to always get from the cached loads. I would still recommend adjusting your code away from that, even if it works in an updated Addressables version.
     
  42. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    I do not believe it's fixed and also believe the issue is deeper than a flag not being read correctly.
    On v1.18.11 when you disable the catalog update on start in settings and run
    Code (CSharp):
    1. IEnumerator UpdateCatalogs()
    2. {
    3.     List<string> catalogsToUpdate = new List<string>();
    4.     AsyncOperationHandle<List<string>> checkForUpdateHandle = Addressables.CheckForCatalogUpdates();
    5.     checkForUpdateHandle.Completed += op =>
    6.     {
    7.         catalogsToUpdate.AddRange(op.Result);
    8.     };
    9.     yield return checkForUpdateHandle;
    10.     if (catalogsToUpdate.Count > 0)
    11.     {
    12.         AsyncOperationHandle<List<IResourceLocator>> updateHandle = Addressables.UpdateCatalogs(catalogsToUpdate);
    13.         yield return updateHandle;
    14.     }
    15. }
    (which is a copy-paste from the docs)
    it always returns 0.

    Which is the bug being mentioned, and your reasoning was because the auto catalog update runs on start regardless of the flag position, BUT I am loading an extra content catalog at runtime and once the
    LoadContentCatalogAsync function is completed there is a hash and json file in my com.addressables folder and if I then delete or edit the hash file to be different from the server and run
    CheckForCatalogUpdates it will still return 0.

    (did these test with and without InitializeAsync running before hand)
     
    Last edited: Oct 11, 2021
  43. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    sniffle63 likes this.
  44. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Yes I have it set to auto-release the handle

    this is the code I am using to load the catalogs at runtime.
    Code (CSharp):
    1.         public static async Task LoadAsync(string url, string suffix = null)
    2.         {
    3.             if (LoadedCatalogs.Contains(url))
    4.                 return;
    5.  
    6.             LoadedCatalogs.Add(url);
    7.             await Addressables.LoadContentCatalogAsync(url, true, suffix).Task;
    8.         }
    9.  
    10.  
    11.         public static IEnumerator Load(string url, string suffix = null)
    12.         {
    13.             if (LoadedCatalogs.Contains(url))
    14.                 yield break;
    15.  
    16.             LoadedCatalogs.Add(url);
    17.             var handle = Addressables.LoadContentCatalogAsync(url, true, suffix);
    18.             yield return handle;
    19.         }
    after using that to load the catalog, then manually changing the hash file on my local computer or deleting it and running CheckForCatalogUpdates it will return 0.
     
  45. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    Your code works as expected for me.
    I attached code I used to check it, check for update after load said 0, then after editing .hash. 1.
     

    Attached Files:

  46. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Will check here in a bit, but from a different post on the forums, it seems to work differently on different unity versions. The post said it works as expected on 2021+, I use 2020 lts.

    Also really appreciate the time.
     
  47. alexaw

    alexaw

    Joined:
    Oct 13, 2015
    Posts:
    1
    I had quite a similar issue as you guys and I feel like I should post my findings here. For me the addressable system was downloading the first iteration of the build but no matter what the settings were, it would not update with further builds.

    I tried using manual checks, and cache the catalogs manually but it would still not work as expected.

    The issue was NOT with the addressable system was with our settings on AWS S3 bucket. My team and I were using AWS cloudfront on top of S3 and it seems that it has some sort of caching in place. (I'm not a technical dev regarding AWS so I can't go into detail).

    After we removed the default caching settings that amazon cloudfront comes with, the addressable system works like a charm. Either with automatic catalog updates or with manual catalog updates. Also the method "CheckForCatalogUpdates" works as expected.
     
  48. EwertonBR

    EwertonBR

    Joined:
    Feb 7, 2018
    Posts:
    18
    Steps that solved it for me:
    • Change Bundle Naming Mode for each group to "
      Append Hash to Filename
      "
    • Initialize Addressable before "
      CheckForCatalogUpdates
      " :
    Code (CSharp):
    1. await Addressables.InitializeAsync();
    2. await Addressables.CheckForCatalogUpdates();
    • Check the "
      Unique Bundle IDs
      " in Addresssables Settings
    • Compile the Addressables
    • Compile the Player