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.