What's the proper way to add an editor-only component?

In one of my actor classes I have some components only intended to be used in editor, so I’ve got the declarations (and any reference to them) covered by #WITH_EDITOR defines. However I’ve run into an issue where I get errors when making non-editor builds. I can fix these errors by removing the defines around the property declarations (but leaving them around any functionality) but I was wondering: Is that the best way to handle editor only components? Declaring them as normal, but using the #WITH_EDITOR defines around any functionality or references to the components?

2 Likes

You need to set bIsEditorOnly to true in the component in constructor when you setup the component, trill will exlude component from asset cooking and level data, regardless what you gonna do that impotent part as you may have errors in cooked assets.

Now WITH_EDITOR should work as a extra thing, this will exlude code from non-editor builds, this also means that you need to cover all references to component in cpp file and elsewhere you trying communicate with or reference component. Not doing WITH_EDITOR should be fine too as bIsEditorOnly should prevent component from startup, but you gonna have dead code in the C++ module, also depending how critical that component is you be leaving traces (mentioned dead code) of it’s existence which potentially can be used by hackers for something.

bIsEditorOnly can be also set in blueprint, and in case of blueprint only components traces of that component will be complitly gone from cooked assets.

Can you paste what error you exactly getting?

1 Like

So here’s the declaration of my component:

  #if WITH_EDITOR
    	UPROPERTY(VisibleDefaultsOnly)
    	class UBoxComponent* EditorCourtBounds;
    #endif

And in the constructor I create it like so:

#if WITH_EDITOR
	EditorCourtBounds = CreateEditorOnlyDefaultSubobject<UBoxComponent>(TEXT("EditorCourtBounds"));
#endif

And the error I get is:

HalfCourt.h(29): error C2039: 'EditorCourtBounds': is not a member of 'AHalfCourt'
HalfCourt.h(27): note: see declaration of 'AHalfCourt'
HalfCourt.h(29): error C2618: illegal member designator in offsetof
HalfCourt.h(29): note: offsetof has a builtin meaning; use /Zc:offsetof- to revert to old, non-conforming definition

Where line 29 is the GENERATED_BODY() macro and line 27 is the class declaration.

First, in the header wrap the component definition using the compiler directive WITH_EDITORONLY_DATA:

#if WITH_EDITORONLY_DATA
	// Reference to editor visualization arrow
private:
	UPROPERTY()
	UArrowComponent* ArrowComponent;
#endif

Second, in the C++ constructor, wrap with the same, and be sure to use CreateEditorOnlyDefaultSubobject instead of the normal CreateDefaultSubobject:

#if WITH_EDITORONLY_DATA
	ArrowComponent = CreateEditorOnlyDefaultSubobject<UArrowComponent>(TEXT("ArrowComponent0"));
	if (ArrowComponent)
	{
		ArrowComponent->ArrowColor = FColor(150, 200, 255);

		ArrowComponent->bTreatAsASprite = true;
		ArrowComponent->SpriteInfo.Category = ConstructorStatics.ID_Lighting;
		ArrowComponent->SpriteInfo.DisplayName = ConstructorStatics.NAME_Lighting;
		ArrowComponent->SetupAttachment(DirectionalLightComponent);
		ArrowComponent->bLightAttachment = true;
		ArrowComponent->bIsScreenSizeScaled = true;
	}
#endif // WITH_EDITORONLY_DATA

Be sure not to reference this component outside of the compiler directive, or your code will seem to work fine in the editor and then fail when you package for a build.

If you search in the Engine source for CreateEditorOnlyDefaultSubobject you can find many examples. Good luck!

2 Likes