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

Does Generate Bundle Packing get randomly stuck half way for anyone else

Discussion in 'Addressables' started by dizzy2003, Jun 24, 2020.

  1. dizzy2003

    dizzy2003

    Joined:
    Nov 25, 2013
    Posts:
    97
    Unity 2019.3.f10
    Addressables 1.9.3 and 1.10.

    I get it about 50% of the time
     
  2. dizzy2003

    dizzy2003

    Joined:
    Nov 25, 2013
    Posts:
    97
    I should probably mention I have all my assets as addressables, and they were all in one group (just all the scenes added to that group)

    I made about 30 more groups and dragged folders in to each group so I got each character mesh and textures and anims as its own group.

    Since doing that the Build gets stuck about 50% of the time, regardless of clean build or not.

    I have just had to simplify my groups in the hope of possibly submitting this game to sony/nintendo/MS in a few weeks
     
  3. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,494
    Check if there's more than 1 asset with the same address. You might also want to try Assets->Reimport All.
     
  4. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    313
    Yes, it gets stuck for me as well. Addressables 1.8.5 with Unity 2019.3.15f1. It didn't happen when I had fewer assets in the system but I saw it once I added more.

    *Edit*
    I found I could debug GenerateBundlePacking.cs and add logs to it. I found it didn't freeze but is instead unusably slow.

    It seems to spend a great deal of time here, on the order of minutes per asset
    Code (CSharp):
    1. // Second pass: Remove References also included by non-circular Referenced Assets
    2.             foreach (var referencedAsset in referencedAssets)
    3.             {
    4.                 var circularRef = referencedAsset.referencedObjects.Select(x => x.guid).Contains(asset);
    5.                 if (circularRef)
    6.                     continue;
    7.  
    8.                 references.RemoveAll(x => referencedAsset.referencedObjects.Contains(x));
    9.             }
    I think the issue is that referencedAsset.referencedObjects is a list instead of a HashSet, so the Select() and Contains() functions are very slow

    Also
    It looks like some of the other files have
    public IProgressTracker ProgressTracker;

    This would provide a lot of benefit as the user otherwise thinks Unity has locked up, and there is in fact no way to tell if it did lock up. I'm not sure how to add it though

    *Edit 2*
    After waiting a while longer it did in fact lock up somewhere in ValidAssetBundle or PackAssetBundle. I didn't have enough logging to say where exactly but I added a breakpoint in every loop and none hit within 30 minutes
     
    Last edited: Sep 11, 2020
  5. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    313
    I modified FilterReferencesForAsset in GenerateBundlePacking.cs, now Generate Bundle Packing takes seconds instead of hours / days / infinite

    90% sure it's correct. I wasn't sure if I should combine ObjectIdentifier lists with duplicate GUID AssetLoadInfo. Since the original code uses a HashSet which just discards duplicates, I did the same thing. Also wasn't sure if ObjectIdentifier.guid is valid to use for equality checks in RemoveAll, assuming it is valid because then I can use the key lookup in the dictionary

    Code (CSharp):
    1. List<GUID> FilterReferencesForAsset(GUID asset, List<ObjectIdentifier> references, HashSet<ObjectIdentifier> previousSceneObjects = null)
    2.         {
    3.             // AssetLoadInfo has List<ObjectIdentifier> referencedObjects;
    4.             // Use Dictionary<GUID, List<ObjectIdentifier>> to represent referencedObjects with the same GUID
    5.             var referencedAssets = new Dictionary<AssetLoadInfo, Dictionary<GUID, List<ObjectIdentifier>>>();
    6.  
    7.             // First pass: Remove Default Resources and Includes for Assets assigned to Bundles
    8.             for (int i = references.Count - 1; i >= 0; --i)
    9.             {
    10.                 var reference = references[i];
    11.                 if (reference.filePath.Equals(CommonStrings.UnityDefaultResourcePath, StringComparison.OrdinalIgnoreCase))
    12.                 {
    13.                     references.RemoveAt(i);
    14.                     continue; // TODO: Fix this so we can pull these in
    15.                 }
    16.  
    17.                 AssetLoadInfo referenceInfo;
    18.                 if (m_DependencyData.AssetInfo.TryGetValue(reference.guid, out referenceInfo))
    19.                 {
    20.                     references.RemoveAt(i);
    21.  
    22.                     // KevinJ: OLD
    23.                     // referencedAssets.Add(referenceInfo);
    24.  
    25.                     // KevinJ: NEW
    26.                     Dictionary<GUID, List<ObjectIdentifier>> referencedObjectsAsDictionary;
    27.                     if (referencedAssets.TryGetValue(referenceInfo, out referencedObjectsAsDictionary) == false)
    28.                     {
    29.                         referencedObjectsAsDictionary = new Dictionary<GUID, List<ObjectIdentifier>>();
    30.                         referencedAssets.Add(referenceInfo, referencedObjectsAsDictionary);
    31.  
    32.                         foreach (var referenceObject in referenceInfo.referencedObjects)
    33.                         {
    34.                             List<ObjectIdentifier> guidConflicts;
    35.                             if (referencedObjectsAsDictionary.TryGetValue(referenceObject.guid, out guidConflicts))
    36.                             {
    37.                                 guidConflicts.Add(referenceObject);
    38.                             }
    39.                             else
    40.                             {
    41.                                 guidConflicts = new List<ObjectIdentifier>();
    42.                                 guidConflicts.Add(referenceObject);
    43.                                 referencedObjectsAsDictionary.Add(referenceObject.guid, guidConflicts);
    44.                             }
    45.                         }
    46.                     }
    47.                     continue;
    48.                 }
    49.             }
    50.  
    51.             // Second pass: Remove References also included by non-circular Referenced Assets
    52.             foreach (var referencedAsset in referencedAssets)
    53.             {
    54.                 // OLD:
    55.                 /*
    56.                 var circularRef = referencedAsset.referencedObjects.Select(x => x.guid).Contains(asset);
    57.                 if (circularRef)
    58.                     continue;
    59.  
    60.                 references.RemoveAll(x => referencedAsset.referencedObjects.Contains(x));
    61.                 */
    62.  
    63.                 // New:
    64.                 Dictionary<GUID, List<ObjectIdentifier>> referencedObjectsAsDictionary = referencedAsset.Value;
    65.                 bool circularRef = referencedObjectsAsDictionary.ContainsKey(asset);
    66.                 if (circularRef)
    67.                     continue;
    68.  
    69.                 references.RemoveAll(x => referencedObjectsAsDictionary.ContainsKey(x.guid));
    70.             }
    71.  
    72.             // Final pass: Remove References also included by circular Referenced Assets if Asset's GUID is higher than Referenced Asset's GUID
    73.             foreach (var referencedAsset in referencedAssets)
    74.             {
    75.                 // OLD:
    76.                 /*
    77.                 var circularRef = referencedAsset.referencedObjects.Select(x => x.guid).Contains(asset);
    78.                 if (!circularRef)
    79.                     continue;
    80.  
    81.                 if (asset < referencedAsset.asset)
    82.                     continue;
    83.  
    84.                 references.RemoveAll(x => referencedAsset.referencedObjects.Contains(x));
    85.                 */
    86.  
    87.                 Dictionary<GUID, List<ObjectIdentifier>> referencedObjectsAsDictionary = referencedAsset.Value;
    88.                 bool circularRef = referencedObjectsAsDictionary.ContainsKey(asset);
    89.                 if (!circularRef)
    90.                     continue;
    91.  
    92.                 if (asset < referencedAsset.Key.asset)
    93.                     continue;
    94.  
    95.                 references.RemoveAll(x => referencedObjectsAsDictionary.ContainsKey(x.guid));
    96.             }
    97.  
    98.             // Special path for scenes, they can use data from previous sharedAssets in the same bundle
    99.             if (!previousSceneObjects.IsNullOrEmpty())
    100.                 references.RemoveAll(previousSceneObjects.Contains);
    101.  
    102.  
    103.             // NEW
    104.             // Write modifications
    105.             foreach (var referencedAsset in referencedAssets)
    106.             {
    107.                 referencedAsset.Key.referencedObjects.Clear();
    108.  
    109.                 Dictionary<GUID, List<ObjectIdentifier>> referencedObjectsAsDictionary = referencedAsset.Value;
    110.                 foreach (var guidToObjectList in referencedObjectsAsDictionary)
    111.                 {
    112.                     referencedAsset.Key.referencedObjects.AddRange(guidToObjectList.Value);
    113.                 }
    114.             }
    115.  
    116.             // OLD
    117.             // return referencedAssets.Select(x => x.asset).ToList();
    118.  
    119.             // NEW
    120.             List<GUID> output = new List<GUID>();
    121.             foreach (var referencedAsset in referencedAssets)
    122.                 output.Add(referencedAsset.Key.asset);
    123.             return output;
    124.         }
    Not sure if anyone from Unity watches this forum, but if this code works for you feel free to use it.
     
    Last edited: Sep 11, 2020