Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question how to use GatherModifiedEntries

Discussion in 'Addressables' started by IS_Twyker, Feb 1, 2022.

  1. IS_Twyker

    IS_Twyker

    Joined:
    Sep 6, 2021
    Posts:
    35
    ContentUpdateScript.GatherModifiedEntries(settings, path); seems to
    always returns a list with all the entries in the AAS - even if there were 0 changes. :/

    • How do I only get modified/changed assets from this?
    • Does ContentUpdateScript.BuildContentUpdate() internally the same basic check?
    I scoured the internet for any clues how to correctly use this, but I don't think I'm doing anything wrong with it?
    Code (CSharp):
    1. var aaSettings = AddressableAssetSettingsDefaultObject.Settings;
    2.             if (aaSettings != null && aaSettings.BuildRemoteCatalog)
    3.             {
    4.                 var statePath = ContentUpdateScript.GetContentStateDataPath(false);
    5.                 if (File.Exists(statePath))
    6.                 {
    7.                     Debug.Log($"Trying to update AAS content instead of full rebuild for {statePath}");
    8.  
    9.                     var changes = ContentUpdateScript.GatherModifiedEntries(aaSettings, statePath);
    10.                     foreach (var changedEntry in changes)
    11.                     {
    12.                         Debug.Log($"changed asset: {changedEntry.address}");
    13.                     }
    14.  
    15.                     var result = ContentUpdateScript.BuildContentUpdate(aaSettings, statePath);
    16.                     if (result != null)
    17.                     {
    18.                         if (result.Error != string.Empty)
    19.                         {
    20.                             Debug.Log("Build error: " + result.Error);
    21.                         }
    22.                         else
    23.                         {
    24.                             Debug.Log($"Updating AAS successful in {result.Duration} seconds.");
    25.                         }
    26.                     }
    27.                 }
    28.             }
     
    Last edited: Feb 3, 2022
  2. IS_Twyker

    IS_Twyker

    Joined:
    Sep 6, 2021
    Posts:
    35
    Ok I kinda got it working now by unchecking all the CRC and Cache flags in the group settings.
    • Am I correct in the assumption that ContentUpdateScript.BuildContentUpdate(...) actually prepares the updated content but you still need to call AddressableAssetSettings.BuildPlayerContent() afterwards?
    or
    • ContentUpdateScript.BuildContentUpdate(...) should work alone just fine but doesn't update/create the bin file? If so, how should we update it?
     
    Last edited: Feb 2, 2022
  3. IS_Twyker

    IS_Twyker

    Joined:
    Sep 6, 2021
    Posts:
    35
    Ok, so I scratched the idea of working with theses files as static. I don't want a new update to rearrange my AAS group structure.

    With non-static, the ContentUpdateScript.BuildContentUpdate(...) alone seems to correctly update the assets/bundles. The only question now is:
    • What is the correct non-static way (method) to get the info which assets/entries have changed, as ContentUpdateScript.GatherModifiedEntries(...) only seems to be working for static bundles?
     
    Last edited: Feb 2, 2022
  4. IS_Twyker

    IS_Twyker

    Joined:
    Sep 6, 2021
    Posts:
    35
    At this point I fear the dynamic (non-static) content is ALWAYS rebuilt in full, as the bin seems to only track static content, is this correct?
    If so, I might have to switch back to static content, detect the changes and then manually build only the bundles that were changed.
    • Is this even possible via the AAS to only build specific bundles?
    • If I were to manually save the cache somewhere to speed up the bundle builds, what exactly from the Library folder do I need to copy out: only Library/com.unity.addressables/ or build cache as well?
     
    Last edited: Feb 3, 2022
  5. IS_Twyker

    IS_Twyker

    Joined:
    Sep 6, 2021
    Posts:
    35
  6. wesmag

    wesmag

    Joined:
    Mar 25, 2020
    Posts:
    34
    Unity Version: 2019.4.32f1
    Addressables: 1.18.19

    @IS_Twyker I am looking into something similar. We have only one bundle marked as "Can Change Post Release" (i.e "non-static") and this changes the behaviour of "ContentUpdateScript.GatherModifiedEntries" completely from what I have observed.

    It will always return 0 entries as having changed in this case unless I set the group to "Cannot Change Post Release" (i.e static). I get the workflow, but in this case you appear to be obligated to create a content update group in order to update this content. Fair enough, but that quickly becomes messy. We work with CI, and in my exploration I have created a script flow that will create a new group to accommodate any changes found by GatherModifiedEntries on the static group. But like I said, this is messy and complicates the workflow and management of all these new groups.

    I am not yet sure how the content state file works internally regarding non-static groups, either way, GatherModifiedEntries doesn't give me updated entries with a non-static (can we just call it "dynamic"?) group. This would be very handy functionality as we would like to execute a versioning step where we generate a version file into the bundle. But only if there are updated entries. This would all happen automatically on CI.

    But maybe I am missing something?

    @unity_bill @davidla_unity can you shed any light on this process please?

    As far as the dynamic group is concerned however, the group will be rebuilt in its entirety if any of the data inside it changes, AFAIK. So you the user will have to download the entire package. Perhaps "Pack Separately" in the group settings is advisable in this case?
     
    IS_Twyker likes this.
  7. wesmag

    wesmag

    Joined:
    Mar 25, 2020
    Posts:
    34
    Also, to add: we're using:

    Code (CSharp):
    1. ContentUpdateScript.CreateContentUpdateGroup(AddressableAssetSettingsDefaultObject.Settings, modifiedEntries, groupName);    
    To create the content update group. We give it a name with a date stamp appended to it. It is entirely possible that we don't do this and just use the same "Update Group" with the same name and manually add the entries to it. This is because the "update group" is always created as "Can Update Post Release" (non-static/dynamic) etc.

    Is this the intention?

    Code (CSharp):
    1. private static void CheckForUpdatedContent()
    2.     {
    3.         string pathToFile = ContentUpdateScript.GetContentStateDataPath(false);
    4.         List<AddressableAssetEntry> modifiedEntries = ContentUpdateScript.GatherModifiedEntries(AddressableAssetSettingsDefaultObject.Settings, pathToFile);
    5.         if (modifiedEntries.Count <= 0)
    6.             return;
    7.      
    8.         Log($"Beginning content build update.");
    9.         StringBuilder updateLogBuilder = new StringBuilder();
    10.         updateLogBuilder.AppendLine($"Assets requiring updates: ");
    11.         foreach (var entry in modifiedEntries)
    12.         {
    13.             updateLogBuilder.AppendLine(entry.address);
    14.         }
    15.          
    16.         Debug.Log(updateLogBuilder.ToString());
    17.         //var groupName = string.Format("Update_Group_{0}", DateTime.UtcNow.ToString("yyyy_MM_dd_HHmmss"));
    18.         var groupName = string.Format("Update_Group_{0}", DateTime.UtcNow.ToString("yyyy_MM_dd"));
    19.  
    20.         AddressableAssetGroup group;
    21.         if (TryGetGroup(AddressableAssetSettingsDefaultObject.Settings, groupName, out group))
    22.         {
    23.             foreach (var entry in modifiedEntries)
    24.             {
    25.                 AddressableAssetSettingsDefaultObject.Settings.CreateOrMoveEntry(entry.guid, group);  
    26.             }
    27.         }
    28.         else
    29.         {
    30.             ContentUpdateScript.CreateContentUpdateGroup(AddressableAssetSettingsDefaultObject.Settings, modifiedEntries, groupName);  
    31.         }
    32.     }
    Naturally, this is no good anyway, as it simply breaks the structure of the group setup and would require a lot more work to maintain it.
     
    IS_Twyker likes this.
  8. wesmag

    wesmag

    Joined:
    Mar 25, 2020
    Posts:
    34
    Of course, you could just generate a single update group that is non-static and use that from that point on. As I understand it, this would be no different than just having a manually created single non-static group.

    Code (CSharp):
    1. private static void CheckForUpdatedContent()
    2.     {
    3.         string pathToFile = ContentUpdateScript.GetContentStateDataPath(false);
    4.         List<AddressableAssetEntry> modifiedEntries = ContentUpdateScript.GatherModifiedEntries(AddressableAssetSettingsDefaultObject.Settings, pathToFile);
    5.         if (modifiedEntries.Count <= 0)
    6.             return;
    7.      
    8.         Log($"Beginning content build update.");
    9.         StringBuilder updateLogBuilder = new StringBuilder();
    10.         updateLogBuilder.AppendLine($"Assets requiring updates: ");
    11.         foreach (var entry in modifiedEntries)
    12.         {
    13.             updateLogBuilder.AppendLine(entry.address);
    14.         }
    15.          
    16.         Debug.Log(updateLogBuilder.ToString());
    17.         //var groupName = string.Format("Update_Group_{0}", DateTime.UtcNow.ToString("yyyy_MM_dd_HHmmss"));
    18.  
    19.         foreach (var entry in modifiedEntries)
    20.         {
    21.             var groupName = string.Format("Update_Group_{0}", entry.parentGroup.Name);
    22.             AddressableAssetGroup group;
    23.             if (TryGetGroup(AddressableAssetSettingsDefaultObject.Settings, groupName, out group))
    24.             {
    25.                 AddressableAssetSettingsDefaultObject.Settings.CreateOrMoveEntry(entry.guid, group);
    26.             }
    27.             else
    28.             {
    29.                 ContentUpdateScript.CreateContentUpdateGroup(AddressableAssetSettingsDefaultObject.Settings, new List<AddressableAssetEntry>() { entry }, groupName);
    30.             }
    31.         }
    32.     }
     
    Last edited: Mar 16, 2022
    IS_Twyker likes this.
  9. IS_Twyker

    IS_Twyker

    Joined:
    Sep 6, 2021
    Posts:
    35
    Yeah, from what I've heard from people who are actually using this in production, they are just doing all dynamic, separated bundles and when building ALL of it, hope for the best from cache/library side. This is really sub-optimal, as we have a new checkout on each PR for instance, with a mostly blank cache/library state. :(