Missing Dependency in packaged build

I have got a crash on packaged build with this message:

Fatal error: [File:D:\Build++UE4+Release-4.16+Compile\Sync\Engine\Source\Runtime\CoreUObject\Private\Serialization\AsyncLoading.cpp] [Line: 2936]
Missing Dependency, request for BillboardComponent but it hasn’t been created yet.

In my game BillboardComponent is an instance of UBillboardComponent which is used for debug purpose only and it is surrounded with define WITH_EDITORONLY_DATA, so I think in packaged build it shouldnt be included.

It is very easy to reproduce on template project. Add to any actor UBillboardComponent surrounded with WITH_EDITORONLY_DATA and try to package game for Windows x64 in debug mode. Next run packaged game and voilà.

Make sure you only use UPROPERTY without any visibility flags and as private variable:

private:
#if WITH_EDITORONLY_DATA
	UPROPERTY()
	class UBillboardComponent* SpriteComponent;
#endif

Make sure you use #if as opposed to #ifdef and that you don’t have any nested #if s or #ifdef s. If you adhere to that the UnrealHeaderTool will flag your property as CPF_EditorOnly: https://github.com/EpicGames/UnrealEngine/blob/4.17/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.cpp#L3148 which will cause your UPROPERTY to be removed during asset cooking.

Also, create your billboard with CreateEditorOnlyDefaultSubobject instead of CreateDefaultSubobject:

SpriteComponent = CreateEditorOnlyDefaultSubobject<UBillboardComponent>(TEXT("Sprite"));

That will have two effects: First, it will create the object with bRequired=false, so that it doesn’t crash if the object class is missing at runtime and it will also call MarkAsEditorOnlySubobject for you. MarkAsEditorOnlySubobject will set bIsEditorOnly = true so that during package save, the reference from your class to the component is tagged as OBJECTMARK_EditorOnly, which will cause the package generator to skip it during cooking https://github.com/EpicGames/UnrealEngine/blob/4.17/Engine/Source/Runtime/CoreUObject/Private/UObject/SavePackage.cpp#L2948

So if your deserialization is crashing because of the missing UPROPERTY, then the #if WITH_EDITORONLY_DATA is not detected correctly by the UnrealHeaderTool. If your deserialization is crashing because the class of your component cannot be loaded, then you probably used CreateDefaultSubobject where you should have used CreateEditorOnlyDefaultSubobject.

And lastly - as a side comment - you can also mark an UPROPERTY as Transient. That way, it just won’t get saved, no matter if you’re compiling for the editor or not. But unlike a regular C++ attribute, you can still edit transient UPROPERTYes in blueprint.That’s very helpful for effect objects which you create dynamically from a template, thus you don’t need to edit them in the editor and they will get re-created anyway. This can greatly improve loading times.

3 Likes

And since its kind of related, and yields the same error as your problem:
Creating an object only on some platforms
Mark the UPROPERTY as transient, so that it doesn’t get saved. No #if around the UPROPERTY here, to keep memory layout the same on all platforms.

	UPROPERTY(Transient)
	class UDestructibleComponent* DestructibleComponent;

Create the object using NewObject in an #if, so that it doesn’t get marked as CDO and with Transient flag:

#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX
DestructibleComponent = NewObject<UDestructibleComponent>(this, "DestructibleComponent", RF_Transient);

That way, the object will not be serialized into the cooked asset as CDO parameters (due to being created with NewObject and not CreateDefaultSubobject), and it won’t be saved itself (due to being transient) so that on platforms where you don’t create it, the Serializer doesn’t complain about its absence.

2 Likes