Unable to access scene path from AssetReference in 1.16.1

My project has ScriptableObjects that have references to multiple scenes, each of which is serialized as a AssetReference type. Prior to Addressables 1.16.1, I have been able to get the path of the asset with the following code, however in 1.16.1, my code fails to return a location for any AssetReference that is assignable from SceneAsset using the AssetReference.RuntimeKey.

My Extension Method:

public static string Path(this AssetReference assetReference)
{
   if (assetReference.RuntimeKeyIsValid() == false)
   {
      Debug.LogError("AssetReference RuntimeKey is invalid.");
      return string.Empty;
   }

   var resourceLocator = Addressables.ResourceLocators.First();
   if ((resourceLocator.Locate(assetReference.RuntimeKey, null, out var locations) == false)
       || (locations.Count == 0))
   {
      Debug.LogError($"Unable to locate AssetReference using its RuntimeKey: {assetReference.RuntimeKey.Bold()}");

      return string.Empty;
   }

   if (locations.Count > 1)
   {
      Debug.LogWarning("Multiple assets were located using the AssetReference.");
   }

   return locations[0].InternalId;
}

Using Addressables 1.15.1, the above method would return the path at line #23, whereas with 1.16.1, the method returns at line #15 after logging the error. The IResourceLocation.InternalId matches the asset path that I’m looking for.

Comparing the 1.15.1 and 1.16.1 packages, the cause of the change appears to be located in AddressableAssetSettingsLocator.GatherEntryLocations().

In 1.15.1, a AddressableAssetEntry object that is associated with a scene (e.Scene == true) and is assignable from SceneAsset or is of type SceneInstance would be used, and the associated asset would be located and returned.

However, in 1.16.1, that same scene object must be of type SceneInstance, otherwise the function fails to locate the asset.

1.15.1 - Code Block from GatherEntryLocations():

if (type == null || type.IsAssignableFrom(e.MainAssetType) || (type == typeof(SceneInstance) && e.IsScene))
{
    var locType = e.IsScene ? typeof(SceneProvider).FullName : typeof(AssetDatabaseProvider).FullName;
    locations.Add(new ResourceLocationBase(e.address, e.AssetPath, locType, e.MainAssetType));
}
else
{
    ObjectIdentifier[] ids = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(e.guid), EditorUserBuildSettings.activeBuildTarget);
    if (ids.Length > 1)
    {
         foreach (var t in AddressableAssetEntry.GatherSubObjectTypes(ids, e.guid))
         {
            if (type.IsAssignableFrom(t))
                locations.Add(new ResourceLocationBase(e.address, e.AssetPath, typeof(AssetDatabaseProvider).FullName, t));
        }
    }
}
return false;

1.16.1 - Code Block from GatherEntryLocations():

if (e.IsScene)
{
    if (type == typeof(SceneInstance))
        locations.Add(new ResourceLocationBase(e.address, e.AssetPath, typeof(SceneProvider).FullName, typeof(SceneInstance)));
}
else if (type == null || type.IsAssignableFrom(e.MainAssetType))
{
    locations.Add(new ResourceLocationBase(e.address, e.AssetPath, typeof(AssetDatabaseProvider).FullName, e.MainAssetType));
}
else
{
    ObjectIdentifier[] ids = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(e.guid), EditorUserBuildSettings.activeBuildTarget);
    if (ids.Length > 1)
    {
        foreach (var t in AddressableAssetEntry.GatherSubObjectTypes(ids, e.guid))
        {
            if (type.IsAssignableFrom(t))
                locations.Add(new ResourceLocationBase(e.address, e.AssetPath, typeof(AssetDatabaseProvider).FullName, t));
        }
    }
}
return false;

I don’t know if the change to exclude SceneAsset objects here was intentional or an oversight. It seems to be intentional.

Not understanding why this change was made makes me wonder if I should be going about this in some other way. Should I be storing serialized AssetReference fields in ScriptableObjects? If so, how can I get access to the IResourceLocation.InternalId from the AssetReference address or key now that SceneAsset types are ignored in AddressableAssetSettingsLocator.GatherEntryLocations()?

Please advise.

Hm, interesting. Let me see what I can find out. Likely this is just a bug introduced by a refactoring of our code.

1 Like

Hey, sorry for the delay. This looks like it’s fixed in 1.16.13. It may have been fixed sooner than that. If you’re still having issues please submit a bug with a repro project.

I apologize for any inconvenience this caused.

2 Likes

@davidla_unity Thanks for replying. We have tried updating to a newer Addressables that contains the fix, but it seems anything past 1.16.10 breaks completely in 2018 LTS (error building addressables).

Please see our post here for details: OutOfRangeException when building bundles with Unity 2018.4.27 and Addressables 1.16.15

Right, yeah, I see that… that’s unfortunate. @Greyborn I think the fix that @Michael-Ryan suggested in the other thread is a valid fix. Hopefully we can get an official fix in soon. I know I sound like a broken record but it really helps out if a bug report gets filed about the SBP issue.

If you use that fix from the other thread on 1.16.15 does this scene path/AssetReference issue still manifest?

@davidla_unity , I’m on the Greyborn team. My SBP fix does seem to allow the Addressable to be built again.

There still appears to be a slow down (40-70 second hang one one frame) after loading an addressable scene at runtime in the editor, but I’m assuming that’s a separate issue. I haven’t looked into the cause, but the profiler appears to indicate that garbage collection associated with the load is being performed for the entire delay (i.e., 70,000 ms). There is no noticeable freeze when loading scenes when using Addressables 1.16.10.

Regarding the scene path/AssetReference issue, I’ve since changed the code that was relying on the scene path, and the method in quest is no longer being called. I will test it out when I get the chance, though. Thanks for following up.