We have recently updated our project from UE5.4 to 5.6 and have observed a regression on one of our features based on `FPackageLocalizationManager`.
To handle assets swap according to certain game conditions, we have implemented our own `IPackageLocalizationCache` which overrides `FindLocalizedPackageName`.
This works pretty well in 5.4, no matter which launch configuration we use : uncooked (-game), cooked or packaged version.
On 5.6, this doesn’t work with cooked one. `FPackageLocalizationManager::FindLocalizedPackageName` is never called and therefore neither is our cache implementation.
The main difference between those two versions is the transition from `FAsyncPackage` to `FAsyncPackage2`.
After more investigation, the reason for this difference between cooked and packaged version comes from `FPackageStore::GetPackageRedirectInfo`.
In cooked version `Backends` is empty because there are no mounted packages, and so next steps are not called :
// Our IPackageLocalizationCache::FindLocalizedPackageName implementation
FPackageLocalizationManager::FindLocalizedPackageName(const FName InSourcePackageName) Line 130
FFilePackageStoreBackend::GetPackageRedirectInfo(FPackageId PackageId, FName & OutSourcePackageName, FPackageId & OutRedirectedToPackageId) Line 373
FPackageStore::GetPackageRedirectInfo(FPackageId PackageId, FName & OutSourcePackageName, FPackageId & OutRedirectedToPackageId) Line 211
Is it a known problem ?
I saw that is possible to fallback on old `FAsyncPackage` with `GUseOldLoaderAsFallback` in `AsyncPackageLoader.cpp`, but it’s not a durable solution.
Can you clarify “In cooked version `Backends` is empty because there are no mounted packages” ?
The PackageStore backends are means to find content on disk (typically staged cooked .ucas data) so I’d expect there to at least be one to allow any loading to happen, and the `FOnDemandPackageStoreBackend::GetPackageRedirectInfo` is implemented to call into `FPackageLocalizationManager::Get().FindLocalizedPackageName`
For your cooked scenario, you are running a non-editor (i.e. not using -game) loading cooked, loose assets, is that correct? (that is, not load .ucas volumes of data). If that is the case there might be an issue where 5.6 doesn’t have a loose cooked backend and is relying on the loaders loose file loading to load anything at all. The downside is that the localization paths where we call `ApplyLocalizationPackageNameRedirects` are wrapped with `WITH_EDITOR`. This would explain why the package case works for you (since that used staged, .ucas, content which will call into `FOnDemandPackageStoreBackend::GetPackageRedirectInfo`.
I imagine locally you could enable those callsites and things would start working for you as expected, but I do want to first clarify your setup to make sure I understand the problem properly.
Our cooked scenario is what you describe. We launch the game from Visual in Development, Test or Shipping and so using cooked assets from `Saved\Cooked\{Platform}`.
In that case, as you mentioned, we don’t have any .ucas and so no backend in FPackageStore.
In our case, the execution flow doesn’t pass through `FOnDemandPackageStoreBackend`.
`IoStoreOnDemand` module is not loading by default, because the Target.bCompileIoStoreOnDemand is false by default, maybe due to the experimental feature state.
I tried to enable it, but nothing changed even in packaged version callstacks.
The cooked version doesn’t work as previously, but packaged version continues to pass through `FPackageStore::GetPackageRedirectInfo` to call `FPackageLocalizationManager::FindLocalizedPackageName` (like bCompileIoStoreOnDemand == false) and not through `FOnDemandPackageStoreBackend::GetPackageRedirectInfo` as I would have expected.
In `FOnDemandPackageStoreBackend` the `FindLocalizedPackageName` call is conditioned by a research on `LocalizedMap`, but this one is empty, I haven’t determined why yet.
I took a look locally and I can see that the loose cooked localization paths in the loader are incorrectly guarded to only run in an editor process. I’ve correct this in //UE5/Main with CL 45209280 which removed the WITH_EDITOR guards I mentioned in my first post -- have you tried that locally?
Loose cooked content is a slower iteration path but with the change in the CL I mentioned if you are cooking localized content the loader should now load it from a runtime and editor process as loose file loading is enabled by default whenever we see no IOStore content is available.
When using IOStore you should ensure the cooker is told which -CookCultures= to expect so the localized content can be cooked and staged appropriately.
Hmm it’s not clear to me why packaged builds would have regressed from 5.4 -> 5.6 in your case. (The loose cooked content -game issue makes sense and is now fixed in 5.6 Main)
Can you share your build steps / command lines for how you are cooking and staging your content, and if possible the cook/staging logs?