Event Driven Loader issues with subobjects

We just integrated 4.14 into our game and I was interested in trying out the Event Driven Loader, but it seems to have issues with some of our content that prevents the cooker from working properly.

We have some slightly unusual content, as we have a lot of blueprints whose class default objects have instanced subobjects (i.e. subobjects referenced via properties with the Instanced specifier). Sometimes these subobjects need to be recreated in PostLoad due to things like properties being deprecated, so in some cases we have a PostLoad function declared on the code class that the blueprint inherits from, which creates a new subobject using NewObject and sets it on an Instanced property.

The CDOs of these blueprints are used at runtime, as they are mostly used for storing designer-editable data, so we don’t want to have to create instances of them at runtime just to read off some default values.

The first issue I came across was that when cooking, if there was a blueprint class A that had a default property referencing another blueprint class B, and if class B’s CDO had subobjects, the cook would fail with this message:

 Can't save X: Graph is linked to external private object Y

and if I let it find the referencers, it would show that A’s CDO was referencing B’s CDO, which was referencing the subobject of B’s CDO, which is the expected chain of references. I didn’t realise this wasn’t allowed, as this exact same content cooks fine with the EDL disabled.

After investigating a bit, I found out that where we have subobjects created from the code class’s constructor with CreateDefaultSubobject, they get the RF_Public flag which seems to prevent this error, but since we’re recreating these objects in PostLoad with just a standard NewObject call and no flags specified, many of our subobjects don’t have RF_Public.

I tried to fix this by adding some PostLoad code to call SetFlags(RF_Public) on all the subobjects (which in fact didn’t work because of this issue: https://issues.unrealengine.com/issue/UE-38234, so eventually I had to hack in a console command to call PostLoad on all the subobjects that had been missed). Setting the RF_Public flag allowed the content to cook successfully, but then when the game tried to load the content, I got this message:

"Could not find import X.Y in package Z, this is probably related to adding stuff we don't need to import map under the 'IsEventDrivenLoaderEnabledInCookedBuilds'."

So it seems that the necessary subobjects are still not being cooked, and the RF_Public flag just prevented the cooker from complaining about it. I noticed that CreateDefaultSubobject adds other flags as well, such as RF_DefaultSubObject, so it could be that adding those to all of our existing subobjects will fix it, but because of the diversity of the content (several code classes, 100+ blueprints based on them) and PostLoad not being reliable, it was such a huge effort just to add RF_Public to them I didn’t want to go any further just based on guesswork.

Do you have any ideas about what might be going wrong here and how we can fix it? Please let me know if there’s any more info you need.

Setting the public flag is definitely necessary, objects inside package A can’t refer to subobjects in B unless they’re public.

As you have discovered EDL is still quite experimental in 4.14. We’ve made several big fixes to it in 4.15 but they’re not 100% done yet. By the time the first 4.15 preview hits EDL should be a lot more stable. The version in 4.14 has a really hard time with subobjects-inside-subobjects which it sounds like you were relying on, so it would be a lot of work to get it working on 4.14 vanilla.

If it’s critical that you ship on 4.14 we’re putting together a branch with some of those fixes, so once that is done I can give you access to that info, but it will be a lot of manual maintenance. Or, if you have enough time to wait for 4.15 I would recommend disabling EDL until 4.15 is released, then turn it on there.

I’m not 100% the fixes on 4.15 will resolve your case, so if you want to make a minimal sample project I would be happy to look at it and verify, but I would only do that if it’s time critical on your end.

Thanks for the detailed info, Ben. The project I’m on can wait for 4.15, but we have another project that is aiming to ship on 4.14, so they might be interested in any fixes that are available for that.

Regarding the public flag, as far as I can tell the private object is not being referenced directly by an object in another package, let me try to give an example:

There are 3 objects: Blueprint CDO A, Blueprint CDO B and Blueprint CDO B’s private subobject B1.

A is referencing B, B is referencing B1, and the problem is that while cooking A, the cooker complains that the object graph contains private object B1, but A isn’t directly referencing B1.

Do you know if this setup is allowed or does B1 definitely need to be public? Surely if B1 needs to be public then all subobjects in any cookable asset will need to be public, as pretty much all subobjects in assets are referenced by their outers.

We are trying to sort these issue out right now. Public or not? Meh, for cooked files it doesn’t really matter except to say we might have to disable the error message.

What is clear is that the EDL is keenly interested in making sure subobjects of CDOs are loaded before we create any instances or load any derived classes. So regardless of if these subobjects are public or not, they need to be in the import table so that we can add the right dependencies.

It is all very icky. The code @head seems really close.

Sounds good, Gil. The effort you’re putting into improving load times in UE4 is very much appreciated. I look forward to trying it again in 4.15 :slight_smile: