Recently we moved a class and added a core redirect for that class. Pretty much everything worked as expected like normal with the redirector apart from one very annoying randomly error we were getting. Below you can see the redirect we added which in most cases, worked just fine.
+ClassRedirects=(OldName=“/Script/Atlas.InventoryComponent”,NewName=“/Script/CCPGameplayInventory.InventoryComponent”)
The error we were seeing randomly, was as follows.
LogUObjectGlobals: Warning: Failed to find object ‘Object /Script/Atlas.InventoryComponent’
That’s all we had to go on, no further information. Given that this was inconsistent to repro, some machines it worked fine and others not, it took a while before we got a semi stable repro to debug against. So, I added the following debug.
LogCook: Display: Waiting for Asset Registry
LogTemp: Display: TOMW-1: /Game/Mining/Data/Items/Live/Weapons/ID_Weapon_MiningTool.ID_Weapon_MiningTool
LogTemp: Display: TOMW-2: /Game/Mining/Data/Items/Live/Weapons/ID_Weapon_MiningTool.ID_Weapon_MiningTool
LogTemp: Display: TOMW-2: /Game/UI/Common/Textures/InventoryIcons/Weapons/T_AMARRAshbornPDW_WeaponIcon_SM.T_AMARRAshbornPDW_WeaponIcon_SM
LogTemp: Display: TOMW-2: /Game/UI/HUD/Equipment/Textures/TUI_MiningLaser_Active.TUI_MiningLaser_Active
LogTemp: Display: TOMW-2: /Game/Mining/Data/Equipment/Tools/EqD_MiningTool_Main.EqD_MiningTool_Main
LogTemp: Display: TOMW-2: /Game/Mining/Data/Equipment/Tools/EqD_MiningTool_Shelved.EqD_MiningTool_Shelved
LogTemp: Display: TOMW-2: /Script/Atlas.InventoryComponent
LogTemp: Display: TOMW-2: /Game/Data/Inventory/Weapons/Extensions/InvExtD_MiningTool_Firmware.InvExtD_MiningTool_Firmware
LogTemp: Display: TOMW-2: /Game/Mining/Data/Inventory/Extensions/InvExtD_MiningTool_Magazine.InvExtD_MiningTool_Magazine
LogUObjectGlobals: Warning: Failed to find object ‘Object /Script/Atlas.InventoryComponent’
As you can see highlighted, the ID_Weapon_MiningTool asset is still trying to load the unredirected class path. The request to the unredirected class is coming from AssetManager.cpp LN 1854 where it issues a load request with an array of PathsToLoad.
This seems to be to be a fault of the AssetManager in how it’s building the PathsToLoad array, it does not seem to be resolving redirectors and is just trying to load whatever reference is there. My suggested fix would be to simply call something like FixupRedirectedAssetPath when building the PathsToLoad array so that redirects are correctly followed.
- What is the expected way that redirects inside bundles are meant to be resolved? Is adding FixupRedirectedAssetPath correct?
- Why is this issue intermitent? What updates the redirection in a bundle? It seems like some machines had state where the redirector had been applied but others did not.
- This was a pain to debug, can you/we add some kind of debug to highlight this issue more clearly?
See below where I added FixupRedirectedAssetPath (denoted by CCP_MOD*)* to find the redirected path to any assets referenced by bundles.
`TArray PathsToLoad;
// Gather asset refs
// <#CCP_MOD>
//
// Follow redirects to ensure we load the correct asset.
//
// UDN: [Content removed]
//
FSoftObjectPath FinalRootPath(NameData->GetAssetPtr().ToSoftObjectPath());
UAssetRegistryHelpers::FixupRedirectedAssetPath(FinalRootPath);
const FSoftObjectPath& AssetPath = FinalRootPath;
// </#CCP_MOD>
if (!AssetPath.IsNull())
{
// Dynamic types can have no base asset path
PathsToLoad.Add(AssetPath);
}
for (const FName& BundleName : NewBundleState)
{
FAssetBundleEntry Entry = GetAssetBundleEntry(PrimaryAssetId, BundleName);
if (Entry.IsValid())
{
for (const FTopLevelAssetPath & Path : Entry.AssetPaths)
{
// <#CCP_MOD>
//
// Follow redirects to ensure we load the correct asset.
//
// UDN: [Content removed]
//
FSoftObjectPath FinalBundlePath(Path);
UAssetRegistryHelpers::FixupRedirectedAssetPath(FinalBundlePath);
PathsToLoad.AddUnique(FinalBundlePath);
// </#CCP_MOD>
}
}
else
{
UE_LOG(LogAssetManager, Verbose, TEXT(“ChangeBundleStateForPrimaryAssets: No assets for bundle %s::%s”), *PrimaryAssetId.ToString(), *BundleName.ToString());
}
}`